views:

205

answers:

5

My development team has run into a design issue. I'm hoping someone can help me clean this part of the architecture up a bit.

In my system, I have an enum with 250 members [one member represents a distinct drop down]. In order to populate the drop downs on any given window, that form sends in the enum members that relate to the drop downs needed, and the drop down information is returned.

In other words, say for example, we have 3 windows. Window A has drop downs X, Y and Z. Window B has drop downs W, X and Y and Window C has drop downs T, U and W. My DropDownType enum would consist of T, U, W, X, Y, Y, and Z. So for a specified window, given the drop downs on that window, I query for the data to appear in those drop downs.

This is a simplified example because my application consists of > 250 distinct drop downs.

As you can imagine, I have a factory setup to return the data for each drop down. And this factory is called for each drop down requested.

    switch (dropDownType)
    {
        case DropDownType.T:
            return (from t in dataContext.GetTable<TableOne>() 
                    select new DropDownDto 
                               { 
                                   DropDownDisplayName = t.ColumnA,
                                   DropDownValue = t.ColumnB
                               }).ToList();
        case DropDownType.U:
            return (from u in dataContext.GetTable<TableTwo>() 
                    select new DropDownDto 
                               { 
                                   DropDownDisplayName = u.ColumnC,
                                   DropDownValue = u.ColumnD
                               }).ToList();
        // etc...
    }

Since I have so many members in this enum, does anyone know of a more elegant way of coding this? Do you think transforming this into factory methods would be helpful (but then we'd have to worry about 250 separate files in our source...)? Is there another pattern out there that is more useful? Just having this HUGE switch statement is getting unmanageable.

Any help is greatly appreciated. Thanks in advance!

+4  A: 

You could create a Dictionary<DropDownType, DropDownDtoDelegate> with each entry containing an enum entry as a key and a delegate to retrieve the drop down data as the value. This would allow you to keep each method that returns a drop down list separate and out of the huge switch statement. You would then have one method to retrieve the delegate, execute it, and return the drop down list data.

Jamie Ide
+1  A: 

There are some solutions to such problems.

  1. You might use a Dictionary to map from the drop downs to your data.

  2. You may even consider moving this mapping data into the database. The amount of data may justfy this this decision.

  3. To remove the additional keys in form of your enum think about using the names of the dropdowns as key.

Here is a really good blog dealing with related issues and suggesting similar solutions.

Back to Basics - Life After If, For and Switch - Like, a Data Structures Reminder

Daniel Brückner
A: 

One option might be to use reflection to handle the enum value. If you have a consistent naming standard for all of the classes involved, there might be a way to dynamically generate the name of the table/collection to query and the name of the DTO to return. It will require a bit of "overhead" code to get it to work, but once you do, it could potentially work for all the different tables.

Andy White
A: 

250 dropdowns?

Orion Edwards
A: 

I would use DynamicMethod to generate code in runtime for each item in the enum. This should be cached in a dictionary, and generated on demand.

With an attribute, you can set the Entity used on each enum, and those 2 properties needed.

I can imagine in something like this.

enum DropDownType { [Configuration(Type = typeof(TableOne), DisplayNameProperty = "ColumnA", ValueProperty = "ColumnB")] T,

[Configuration(Type = typeof(TableTwo), DisplayNameProperty = "ColumnC", ValueProperty = "ColumnD")] U }

When you have an enum value, you check the dictionary for the cached method, if not present, you generate it.

Using reflection you get those property infos, and with a bit of IL skill, this can be done easily.