如何使用Activator.CreateInstance创建一个没有构造函数的类型?

3

For example:

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

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

那么 obj.a==1obj.b==2 是什么意思?有人知道如何解决我的问题吗?

3
为什么在创建实例后不能分配值,比如 obj.a=1 和 obj.b=2? - npo
你能添加构造函数或方法吗?还是它是第三方程序集中的一个类? - Reinstate Monica Cellio
  1. 类型确实有构造函数,除非它是静态类型,否则编译器会提供默认构造函数。
  2. 不,框架中没有构造函数调用或类似的东西可以实现你想要的关于赋值的操作。Antoine 在下面的回答是你能得到的最接近的答案,除非你添加缺失的构造函数。
- Lasse V. Karlsen
由于TestType类只是一个数据类,没有方法,我有许多数据类。我不想为这些类创建构造函数。我必须通过反射来创建它们。 - sericaer
3个回答

8

不可能,改为尝试

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

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

这是重载的 Activator.CreateInstance(type, params object[] args) 方法,其中 args 是构造函数的输入参数。因此,您可以使用 Antoines 的解决方案或将测试类型类更改为:
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;
}

0

你把事情搞混了。语法new TestType { a=1, b=2 }并不是调用构造函数,而是一种快捷方式,可以在一次操作中调用隐式或默认构造函数并设置一些属性。但所有的类都有构造函数,至少有一个隐式构造函数。

我不知道你的最终目标是什么,但如果你使用Activator来创建实例,那么你可能在编译时没有类型。因此,你无法通过类型本身访问属性,你需要调用PropertyInfo.SetValue(https://learn.microsoft.com/en-us/dotnet/api/system.reflection.propertyinfo.setvalue?view=netframework-4.7.2)。

请参考以下示例:

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}");
}

在这个最后的代码行中,我重新引入了编译时类型,只是为了展示构造的对象已经按照我们期望的设置成员。
通常情况下,您最有可能寻找扩展某些基本类型或实现接口的类型,但也可能存在从配置中获取完全限定类型名称的情况。

你可以将构造函数语法和对象初始化语法结合起来使用,这样就能够简单地“构造对象”并“分配成员”,也就是说,如果该类型有一个接受单个参数的构造函数,则可以执行此操作:new TestType(1) { b = 2 } - Lasse V. Karlsen
@LasseVågsætherKarlsen 这是真的,但基于问题,可能对OP来说太复杂了。 - ZorgoZ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接