How to create InstanceDescriptor for List of enum?

498 views Asked by At

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

2

There are 2 answers

0
Michael Liu On BEST ANSWER

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() });
1
Salah Akbari On

Your list should be an empty collection because constructor is the parameterless constructor your code should look like this:

List<MyEnum> list = new List<MyEnum>();
ConstructorInfo constructor = typeof(List<MyEnum>).GetConstructor(Type.EmptyTypes);
InstanceDescriptor idesc = new InstanceDescriptor(constructor, list);

Or use a null constructor:

ConstructorInfo constructor = 
  typeof(List<MyEnum>).GetConstructor(BindingFlags.ExactBinding, null,Type.EmptyTypes, null);

That means: the EmptyTypes field used in one of the GetConstructor methods to get a constructor that takes no parameters.