Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flexible object creation in C#

Tags:

c#

asp.net

I'm creating a custom web server control (extends Panel) that contains a ListControl object. I want the ListControl type to be flexible, i.e. allow the type of the ListControl to be specified in the aspx markup. Currently I'm examining the user's choice and initialising the control using a switch statement:

public ListControl ListControl { get; private set; }

private void InitialiseListControl(string controlType) {
        switch (controlType) {
            case "DropDownList":
                ListControl = new DropDownList();
                break;
            case "CheckBoxList":
                ListControl = new CheckBoxList();
                break;
            case "RadioButtonList":
                ListControl = new RadioButtonList();
                break;
            case "BulletedList":
                ListControl = new BulletedList();
                break;
            case "ListBox":
                ListControl = new ListBox();
                break;
            default:
                throw new ArgumentOutOfRangeException("controlType", controlType, "Invalid ListControl type specified.");
        }
    }

Surely there is a more elegant way to do this... obviously I could allow the client code to create the object instead but I want to eliminate the need to use any code other than the aspx markup. Any suggestions would be appreciated. Thanks.

like image 741
kad81 Avatar asked Mar 25 '23 03:03

kad81


2 Answers

You could use a dictionary:

Dictionary<string, Type> types = new Dictionary<string, Type>();
types.Add("DropDownList", typeof(DropDownList));
...

private void InitialiseListControl(string controlType)
{
    if (types.ContainsKey(controlType))
    {
        ListControl = (ListControl)Activator.CreateInstance(types[controlType]);
    }
    else
    {
        throw new ArgumentOutOfRangeException("controlType", controlType, "Invalid ListControl type specified.");
    }
}

but if you want to be even more flexible, you can bypass the dictionary and use a little bit of reflection:

private void InitialiseListControl(string controlType)
{
    Type t = Type.GetType(controlType, false);
    if (t != null && typeof(ListControl).IsAssignableFrom(t))
    {
        ListControl = (ListControl)Activator.CreateInstance(t);
    }
    else
    {
        throw new ArgumentOutOfRangeException("controlType", controlType, "Invalid ListControl type specified.");
    }
}
like image 98
p.s.w.g Avatar answered Apr 01 '23 17:04

p.s.w.g


EDIT: Or if you want the consumer to only have access to the class (since the method is private) you could make the class generic

public class MyController<TList> where TList : ListControl, new()
{
    public TList ListControl { get; private set; }
}

Check out http://weblogs.asp.net/leftslipper/archive/2007/12/04/how-to-allow-generic-controls-in-asp-net-pages.aspx


This sounds like you may want to use generics

private void InitialiseListControl<TList>() where TList : ListControl, new()
{
    ListControl = new TList();
}

See MSDN docs for more information on generic methods: http://msdn.microsoft.com/en-us/library/twcad0zb(v=vs.80).aspx

Note, the article explains generic methods and how the where keyword is used. But it doesn't explain how the new keyword is used. The new keyword specifies that the type argument you provide must have a default constructor. A comment below the article gives another example that uses the new keyword.

like image 33
Steven Wexler Avatar answered Apr 01 '23 16:04

Steven Wexler