简体   繁体   中英

How to Activator.CreateInstance a type which have not constructors?

For example:

class TestType
{
   public int a;
   public int b;
}

TestType obj = Activator.CreateInstance(typeof(TestType), 1, 2) as TestType;

Then obj.a==1 and obj.b==2 ? Does someone knows how to solve my problem?

Impossible, try instead

TestType obj = Activator.CreateInstance(typeof(TestType)) as TestType;
obj.a = 1;
obj.b = 2;
TestType obj = Activator.CreateInstance(typeof(TestType), 1, 2) as TestType;

This is the overload Activator.CreateInstance(type, params object[] args); where args are the input for the constructor. So you can use either Antoines solution or change the test type class to:

TestType obj = Activator.CreateInstance(typeof(TestType), 1, 2) as TestType;

class TestType
{
    public TestType(int a, int b)
    {
        this.a = a;
        this.b = b;
    }

    public int a;
    public int b;
}

You are confusing things. The syntax new TestType { a=1, b=2 } is not calling the constructor. It is a shortcut for calling the implicit or default constructor and setting some properties in one shot. But all classes have constructors. At least the implicit one.

I don't know what is your final goal, but if you are using Activator to create an instance, then you probably don't have the type at compile time. Thus you can't access the properties via the type itself, you will need to call PropertyInfo.SetValue ( https://docs.microsoft.com/en-us/dotnet/api/system.reflection.propertyinfo.setvalue?view=netframework-4.7.2 )

See following example:

class TestType
{
    public int a;
    public int b;
}

void Main()
{
    var typeName = typeof(TestType).FullName; // we have a string from here on

    var type = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x => x.FullName == typeName); // get the type based on the name

    var obj = Activator.CreateInstance(type); // object of this type, but without compile time type info

    var member = type.GetField("a"); // we know, that this is a field, not a property   
    member.SetValue(obj, 1); // we set value to 1
    member = type.GetField("b");
    member.SetValue(obj, 2); // we set value to 2

    Console.Write($"See values: a={((TestType)obj).a}, b={((TestType)obj).b}");
}

In this last code row I have reintroduced the compile-time type, just to show that the constructed object has the members set as we expect them to be set.

In general you will most likely look for types that extend some base type or implement an interface, but it might well be cases when you have the fully qualified type name from the configuration for example.

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