使用反射在C#中没有默认构造函数创建类型的实例
-
23-08-2019 - |
题
以下面的类作为示例:
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()
将不调用一个构造函数创建实例。我用反射并通过一些核心的挖掘发现了这个类。净系列化类。
我测试使用以下示例代码,它看起来像它巨大的:
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
)
创建指定的一个实例 键入使用构造最 符合指定的参数。
当我基准 (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;
}
这意味着创建表达被有效地高速缓存,并且招致处罚仅在第一次的类型被加载。将处理值类型也以有效的方式。
调用它:
MyType me = New<MyType>.Instance();
注意(T)FormatterServices.GetUninitializedObject(t)
将字符串失败。字符串因此特别处理到位返回空字符串。的
好答案,但不能用在点净紧凑框架。这里是一个将在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);
}
}
不隶属于 StackOverflow