简体   繁体   中英

How to create a value type or string type object at runtime using Reflection

Probably simple but could not figure out. I am loading an assembly at runtime and browsing through some classes and generating input controls for its properties. To create an instance of an object at runtime I am using:

  object o =  PropertyType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Type.EmptyTypes,null).Invoke(null);

and it works fine for class types. When the type is an array, I use

  object o =  PropertyType.Type.GetConstructor(new Type[] { typeof(int) }).Invoke(new object[] { 0 });

which also works fine. But when it comes to string type or value types GetConstructor.Invoke does not work. I also tried Activator.CreateInstance which also did not work.

What you're running into is that value types don't really have parameterless constructors. C# makes it look like they do, but they don't at the CLR level.

Activator.CreateInstance should work fine for real value types though:

object o = Activator.CreateInstance(typeof(int));
Console.WriteLine(o); // Prints 0

This will always give the default value for any value type.

Now, you're asking about strings - what string would you expect to create? The default value for the string type is null - but would you want the empty string instead? If so, you'll need to special-case that code.

If you want to be able to instantiate arbitrary objects with particular values, one thing you can check is if there is a TypeConverter that supports converting an instance (with the value you want to match) to an InstanceDescriptor . I'm not entirely sure what you're doing (your example suggests you're trying to create 'default' instances of the different objects), but just thought I'd mention this in case it's relevant. I use this in Emit code to emit arbitrary constant values to the stack via IL. Here's the snippet that gets the InstanceDescriptor:

        var converter = TypeDescriptor.GetConverter(value);
        if (converter.CanConvertTo(typeof (InstanceDescriptor)))
        {
            var desc = (InstanceDescriptor) converter.ConvertTo(value, typeof (InstanceDescriptor));
        }

The descriptor specifies a means of constructing the instance, which could be calling a constructor, calling a static method, accessing a static property or accessing a static field. It also specifies whether the construction completely sets the value of the type to match your original instance; if not, you'll need to do additional reflection and setting of properties.

This is the mechanism that the WinForms Designer uses when generating the code-behind for the controls on the form, so it is supported for the common types that show up as properties of controls accessible from the designer.

The int type doesn't have any constructors .

The code you write is going to depend on the property's type; normally, you'd write special-case code for string , int and other primitive types.

Your code above contains the literal 0; how do you decide what values to pass to the constructors?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM