Search code examples
c#asp.netcustom-controlstypeconvertertypedescriptor

How to create InstanceDescriptor for List of enum?


Similar question: Passing int list as a parameter to a web user control
Is there any similar example for enum type?

I am creating a asp.net custom control in which I want to pass comma separated list of enums as property.
I am writing a TypeConverter for converting comma separated string values to List of Enum.

In the ConvertTo method,
How to create InstanceDescriptor object for list of enum?

My current code is as follows:

//enum
public enum MyEnum {Hello, World}

//main method
List<MyEnum> list = new List<MyEnum>();
list.Add(MyEnum.Hello);
list.Add(MyEnum.World);
ConstructorInfo constructor = typeof(List<MyEnum>).GetConstructor( Type.EmptyTypes );
InstanceDescriptor idesc = new InstanceDescriptor(constructor, list);

This fails with the message

Length mismatch

I wonder why


Solution

  • The "Length mismatch" error occurs because you retrieve the default List<T> constructor, which has ZERO arguments, and then you ask InstanceDescriptor to call that constructor with TWO arguments, MyEnum.Hello and MyEnum.World.

    You might think that you could use the alternate List<T> constructor that accepts a single IEnumerable<T> argument:

    ConstructorInfo constructor =
        typeof(List<MyEnum>).GetConstructor(new[] { typeof(IEnumerable<MyEnum>) });
    InstanceDescriptor idesc = new InstanceDescriptor(constructor, new[] { list });
    

    This makes InstanceDescriptor happy, but unfortunately, you'll find that ASP.NET now throws NullReferenceException instead (same as in the question you linked to) because ASP.NET doesn't know how to deal with IEnumerable<T> parameters.

    Here are two ways to solve the problem.

    Solution 1: Change your custom control and your type converter to use MyEnum[] instead of List<MyEnum>. This works because ASP.NET can handle arrays.

    Solution 2: Create a static helper method that creates a List<MyEnum> from an array:

    public static List<MyEnum> ToList(MyEnum[] values)
    {
        return new List<MyEnum>(values);
    }
    

    Then change your type converter to create an InstanceDescriptor that calls the helper method, passing it your list as an array:

    MethodInfo method = typeof(MyEnumListConverter).GetMethod("ToList");
    InstanceDescriptor idesc = new InstanceDescriptor(method, new[] { list.ToArray() });