views:

402

answers:

1

The issue I'm currently having is mapping multiple GUI fields to object properties (i.e. Presentation layer to Business Logic Layer mapping). To be more specific, this is in VB.Net 2.0 WinForms.

The nature of the solution requires us to have 4 columns which exhibit the same type of behavior on our GUI - each column consisting of 11 textboxes (we'll just use this small sample size, as the problem extends beyond 11 textboxes).

What I am currently doing is setting the tag of each textbox in all four columns to a value like so:

Textbox1.tag = "name"
Textbox2.tag = "type"
Textbox3.tag = "speed"

When an event is raised by the textbox (e.g. keypress), I look at the parent container, whose tag I have also set as a string mapping a specific object. I use that, in conjunction with the textbox's tag, to determine what object's property I need to set. Overall, it looks something like this:

dim objectToMapTo //the generic parent object which all my custom myObjects inherit from

select case sender.parent.tag //the parent object that the property needs to map to
    case "column1"
         objectToMapTo = myObject1
    case "column2"
         objectToMapTo = myObject2
    case "column3"
         objectToMapTo = myObject3
    case "column4"
         objectToMapTo = myObject4
end select

select case sender.tag //the actual textbox's tag value which maps to the property
    case "name"
         objectToMapTo.Name = sender.text //sender.text is conceptual for 
        //the data that needs to be set -- i.e. this could be a calculated 
        //number based on the text, or simply a string, etc
    case "type"
         objectToMapTo.Type = sender.text
    case "speed"
         objectToMapTo.Speed = sender.text
    ...
end select

As you can see this can get very bad, rather quickly. Currently we're setting 43 some odd properties that can be mapped to -- thus that select statement is extremely long -- many of which are embedded in multiple methods to try and attempt DRY (I've watered down the code to essentially a conceptual implementation).

Question is: how can I refactor this? I've attempted using a dictionaries/hashes to a certain extent, but it either became overly complex, or just plain didn't make an implementation sense as it convoluted the problem even more.

Thanks for the help.

+1  A: 

the first problem you sol by setting the tag as the object. Since tag is not string but of type object.

And the second problem you solve by usin reflection but than the value in the tag must match the propertyname exactly.

_objectToMapTo.GetType().InvokeMember(sender.tag,BindingFlags.Instance Or BindingFlags.Public,Nothing, _objectToMapTo, New Object() {sender.text})

Disclaimer the reflection is close but perhaps not 100% correct.

chrissie1
the reflection would work well actually. Only thing is that each value is set a little more complex. So we might have it like objectToMap.Customer.Name = sender.text and then objectToMap.Asset.Type = sender.text -- so it basically needs to get/set nested properties which gives it an added layer of complexity
MunkiPhD
I answered the question but if you change the rules I have to change the answer. YOu problem with nested properties is also easily solved with reflection BTW. But that wasn't the question.
chrissie1