没有无参数构造函数的类型的Activator.CreateInstance(Type)

时间:2010-03-23 15:26:44

标签: c# .net

在工作中阅读现有代码,我想知道这怎么可行。我在程序集中定义了一个类:

[Serializable]
public class A
{
    private readonly string _name;
    private A(string name)
    {
        _name = name;
    }
}

在另一个集会中:

public void f(Type t) {
    object o = Activator.CreateInstance(t);
}

和那个简单的电话f(typeof(A))

我期待一个关于缺少无参数构造函数的例外,因为AFAIK,如果声明了ctor,编译器不应该生成默认的公共无参数构造函数。

此代码在.NET 2.0下运行。

[编辑]我很抱歉,但我误读了实际代码......我提供的示例并没有说明。我接受了JonH的答案,因为它提供了很好的信息。

4 个答案:

答案 0 :(得分:24)

另一种选择是:

object obj = System.Runtime.Serialization.FormatterServices
          .GetUninitializedObject(t);

在内存中创建对象,但运行任何构造函数。吓人。

答案 1 :(得分:10)

请参阅:Creating instance of type without default constructor in C# using reflection

这也是未来,这是关于C#4.0:

  

微软于2010年1月4日发表于   下午2:08
  我们已经审核了您的错误   已经确定了那种行为   你描述的是设计。我们现在   归档此问题。谢谢你的使用   Visual Studio和.Net Framework!

     
    

Activator.CreateInstance有很多重载     仅采用单个类型参数     调用默认的无参数     构造函数。采取的建设者     可选参数,例如     你的例子不是默认的     构造函数。要调用它们,你需要     到:

         
        
  1. 使用带参数数组的重载
  2.     
  3. 传入Type.Missing作为参数
  4.     
  5. 在BindingFlags
  6. 中指定OptionalParamBinding               

    以下是一个例子:

    Activator.CreateInstance(typeof(MyClassName),
     BindingFlags.CreateInstance |
     BindingFlags.Public |
     BindingFlags.Instance |
     BindingFlags.OptionalParamBinding,
     null, new Object[] {Type.Missing}, null);
    
             

    谢谢,

             苏伟涛

             

    微软公司

      

答案 2 :(得分:0)

这对你来说可能不太可行,但最简单的方法是在类型之后传递参数列表:

Activator.CreateInstance(t,“name”);

你会想到f()真正想要做什么。是否应该实例化A类型的对象?它将实例化哪些其他类?

一种可能性是在f()中有一个switch语句,它将正确的参数传递给A类的CreateInstance()。这不会扩展,但这对你来说可能不是问题。

答案 3 :(得分:0)

CreateInstance有两种令人困惑的风格:一种将对象类型System.Type作为参数,另一种采用< strong>类型参数 T

第一个:

object Activator.CreateInstance(type As Type) { }

第二个:

T Activator.CreateInstance<T>() { }

第二个是一个不适用于没有公共无参数构造函数的类。

请注意,即使使用第二个也几乎没有意义;在任何使用它的情况下,最好在你的类上有一个where T : new()约束,只需使用T的构造函数。

MSDN documentation同意:

  

一般情况下,没有用   应用程序代码中的CreateInstance,   因为必须知道类型   编译时间。如果类型已知   编译时,正常实例化   语法可以使用(new运算符   Visual Basic中的C#,Newgcnew中   C ++)。

编辑:我可能说得太早;似乎第一个版本也不应该工作。