Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 586
Nitin S Avatar asked Aug 14 '15 13:08

Nitin S


2 Answers

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() });
like image 192
Michael Liu Avatar answered Sep 18 '22 15:09

Michael Liu


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.

like image 39
Salah Akbari Avatar answered Sep 17 '22 15:09

Salah Akbari