使用reflection在C#中创build没有默认构造函数的types实例
以下面的课程为例:
class Sometype { int someValue; public Sometype(int someValue) { this.someValue = someValue; } }
然后我想使用reflection来创build这种types的实例:
Type t = typeof(Sometype); object o = Activator.CreateInstance(t);
通常这是可行的,但是因为SomeType
没有定义一个无参数的构造函数,所以对Activator.CreateInstance
的调用会抛出一个types为MissingMethodException
的exception,消息是“ 没有为这个对象定义无参数的构造函数 ” 。是否还有另一种方法来创build这种types的实例? 将无参数的构造函数添加到我的所有类中会有点儿麻烦。
我最初在这里发布了这个答案,但这里是一个转载,因为这不是完全相同的问题,但具有相同的答案:
FormatterServices.GetUninitializedObject()
将在不调用构造函数的情况下创build一个实例。 我通过使用Reflectorfind了这个类,并通过一些核心的.Net序列化类来挖掘。
我使用下面的示例代码对其进行了testing,看起来效果很好:
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 )
使用最符合指定参数的构造函数创build指定types的实例。
请参阅: http : //msdn.microsoft.com/en-us/library/wcxyzt4d.aspx
当我对(T)FormatterServices.GetUninitializedObject(typeof(T))
性能进行基准testing时,速度较慢。 同时编译expression式会给你很大的速度提升,尽pipe它们只能用于具有默认构造函数的types。 我采取了混合的方法:
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; }
这意味着创buildexpression式被有效地caching,并且仅在该types第一次加载时才会受到惩罚。 将以有效的方式处理值types。
叫它:
MyType me = New<MyType>.Instance();
请注意(T)FormatterServices.GetUninitializedObject(t)
将失败的string。 因此,对string进行特殊处理以返回空string。
很好的答案,但在networking紧凑框架无法使用。 这是一个可以在CF.Net上运行的解决scheme
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); } }