使用反射在C#中创建没有默认构造函数的类型实例

使用反射在C#中创建没有默认构造函数的类型实例,c#,reflection,instantiation,default-constructor,C#,Reflection,Instantiation,Default Constructor,以下面的类为例: class Sometype { int someValue; public Sometype(int someValue) { this.someValue = someValue; } } 然后,我想使用反射创建此类型的实例: Type t = typeof(Sometype); object o = Activator.CreateInstance(t); 正常情况下,这将起作用,但是,因为SomeType尚未定义无参

以下面的类为例:

class Sometype
{
    int someValue;

    public Sometype(int someValue)
    {
        this.someValue = someValue;
    }
}
然后,我想使用反射创建此类型的实例:

Type t = typeof(Sometype);
object o = Activator.CreateInstance(t);

正常情况下,这将起作用,但是,因为
SomeType
尚未定义无参数构造函数,因此对
Activator.CreateInstance
的调用将引发类型为
MissingMethodException
的异常,并显示消息“未为此对象定义无参数构造函数”是否有其他方法仍然可以创建此类型的实例?在我所有的类中添加无参数构造函数有点糟糕。

我最初发布了这个答案,但这里是一个重印,因为这不是完全相同的问题,但有相同的答案:


FormatterServices.GetUninitializedObject()
将创建实例而不调用构造函数。我通过使用和挖掘一些核心的.Net序列化类发现了这个类

我使用下面的示例代码对其进行了测试,看起来效果很好:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.Serialization;

namespace NoConstructorThingy
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myClass = (MyClass)FormatterServices.GetUninitializedObject(typeof(MyClass)); //does not call ctor
            myClass.One = 1;
            Console.WriteLine(myClass.One); //write "1"
            Console.ReadKey();
        }
    }

    public class MyClass
    {
        public MyClass()
        {
            Console.WriteLine("MyClass ctor called.");
        }

        public int One
        {
            get;
            set;
        }
    }
}

使用CreateInstance方法的此重载:

public static Object CreateInstance(
    Type type,
    params Object[] args
)
创建指定对象的实例 使用最好的构造函数键入 匹配指定的参数


请参阅:

答案很好,但在dot net compact框架上无法使用。这里有一个将在CF.Net上运行的解决方案

class Test
{
    int _myInt;

    public Test(int myInt)
    {
        _myInt = myInt;
    }

    public override string ToString()
    {
        return "My int = " + _myInt.ToString();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var ctor = typeof(Test).GetConstructor(new Type[] { typeof(int) });
        var obj = ctor.Invoke(new object[] { 10 });
        Console.WriteLine(obj);
    }
}
当我检查
(T)FormatterServices.GetUninitializedObject(typeof(T))
的性能时,速度会变慢。同时,编译表达式将给您带来极大的速度提升,尽管它们只适用于具有默认构造函数的类型。我采取了一种混合方法:

public static class New<T>
{
    public static readonly Func<T> Instance = Creator();

    static Func<T> Creator()
    {
        Type t = typeof(T);
        if (t == typeof(string))
            return Expression.Lambda<Func<T>>(Expression.Constant(string.Empty)).Compile();

        if (t.HasDefaultConstructor())
            return Expression.Lambda<Func<T>>(Expression.New(t)).Compile();

        return () => (T)FormatterServices.GetUninitializedObject(t);
    }
}

public static bool HasDefaultConstructor(this Type t)
{
    return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
}
公共静态类新建
{
public static readonly Func Instance=Creator();
静态函数创建者()
{
类型t=类型(t);
if(t==typeof(string))
返回Expression.Lambda(Expression.Constant(string.Empty)).Compile();
if(t.HasDefaultConstructor())
返回表达式.Lambda(Expression.New(t)).Compile();
return()=>(T)FormatterServices.GetUninitializedObject(T);
}
}
公共静态bool hasdaultconstructor(此类型为t)
{
返回t.IsValueType | | t.GetConstructor(Type.EmptyTypes)!=null;
}
这意味着create表达式被有效缓存,并且只有在第一次加载类型时才会受到惩罚。也将以高效的方式处理值类型

叫它:

MyType me = New<MyType>.Instance();
MyType me=New.Instance();

请注意,
(T)FormatterServices.GetUninitializedObject(T)
将因字符串而失败。因此,对字符串的特殊处理已经到位,可以返回空字符串。

太棒了,看起来这正是我需要的。我假设未初始化意味着它的所有内存都将设置为零?(类似于结构的实例化方式)每个类型的默认值都是默认值。所以对象将为null,int为0,等等。我确实认为任何类级别的初始化都会发生,但没有运行构造函数。@JSBangs,这太糟糕了,你给出了一个完全合法的答案。你的评论和另一个答案实际上并没有解决问题。如果你觉得你有一个更好的答案,那么提供一个。但我提供的答案强调了如何使用文档化类,就像其他序列化类使用此代码一样。@JSBangs FormatterServices()不是未文档化的。使用GetUninitializedObject似乎取决于您的特定用途:这是我调用非默认构造函数的方式。我不确定我是否希望在不调用任何构造函数的情况下创建一个对象。如果您正在编写自定义序列化程序,则可能希望在不调用构造函数的情况下创建一个对象。是的,这正是此问题所针对的用例场景:)@Aistina也许您可以将此信息添加到问题中?大多数人会反对在不调用他们的CTOR的情况下创建对象,并且会花时间与您争论,但您的用例实际上证明了这一点,因此我认为这与问题本身非常相关。奇怪的是,看一行代码可以节省一天的时间。谢谢你,先生!性能方面的原因让我看到了你的帖子,诀窍就完成了:)FormatterServices和Activator类的性能比编译表达式差,很遗憾到处都是Activator。@nawfal关于你对字符串的特殊处理,我知道如果没有这种特殊处理,对字符串的处理会失败,但我只是想知道:它会适用于所有其他类型吗?@Sааааааааӽ不幸的是不会。给出的示例是barebones和.NET有许多不同类型的类型。例如,如果您通过委托类型,您将如何给它一个实例?或者,如果构造函数抛出,您可以对此做些什么?有很多不同的处理方法。在回答这个问题之后,我更新了我的库,以处理更多的场景。它现在还没有发布到任何地方。
FormatterServices.GetUninitializedObject
不允许创建未初始化的字符串。您可能会遇到异常:
System.ArgumentException:无法创建未初始化的字符串。
请记住这一点。谢谢提醒,但我已经在分别处理字符串和基本类型。此解决方案将问题简化了。如果我不知道我的类型,我说的是“只需在这个类型变量中创建一个类型的对象”,该怎么办?