【问题标题】:Possible to create a new instance of a type without reflection?可以在没有反射的情况下创建类型的新实例吗?
【发布时间】:2011-01-14 02:02:18
【问题描述】:

我有一个函数,此时需要一个Type 变量。该函数将其粘贴在列表中,并且最终需要将创建该类型的类。

我现在这样做

object o=MyType.GetConstructors()[0].Invoke(new object[0]);

这很 hacky,并且由于反射(我认为)也不会在中等信任下工作。有没有更好的方法来做到这一点而无需反思?

Type 以这种方式定义为函数的一部分。我需要“懒惰地”创建该类,因为如果不需要它,它可能不会在应用程序中创建。例如,我使用它

AddToList(typeof(Whatever)); 

请注意,我愿意接受有关更改函数调用的建议。我只需要延迟创建对象并将类型(或者创建该类型的对象)存储在列表中。

我考虑过 lambda,但我不确定它们是否可以在这里工作。

【问题讨论】:

标签: c# asp.net reflection medium-trust


【解决方案1】:

使用泛型:

public void Method<T>() where T : class, new()
{
  //code
  T t = new T();
}

使用Activator(还是反射,嗯):

object t = Activator.CreateInstance(yourTypeVariable);

就我个人而言,由于是强类型,我更喜欢第一种解决方案。但是,您应该知道这两种方法都只允许无参数构造函数。如果需要传递参数,则需要反射或表达式树。

【讨论】:

  • Activator.CreateInstance() 确实支持参数,它将它们作为对象[]
  • 啊,对。我现在也读了。但是,由于枚举类型对象始终是可能的,因此表达式树应该可以工作(您需要使用一些反射来获取表达式的 MemberInfos)。
  • @Earlz 甚至 new T() 是反射(用于类)。
  • 你确定吗?泛型是一个编译时特性(即编译时类型是已知的)。我不认为这是反射(它是类型信息的运行时查找)。
【解决方案2】:

另一个替代解决方案是FormatterServices

object instance = FormatterServices.GetUninitializedObject(typeof(MyClass));

请注意,创建实例时没有初始化任何字段/属性,即使您已经

class MyClass
{
   public int i = 99;
   public Object o = new object();
}

instance.i 将为 0,instance.o 将为空。提供纯粹的非反射解决方案非常困难(因为您总是需要致电o.GetType())。这个方案本质上是序列化对象,然后反序列化成对象,所以不需要使用反射来调用它的构造函数。但是在序列化/反序列化的时候还是有反射的。

【讨论】:

  • +1,但并不是说FormatterServices.GetUninitializedObject(typeof(MyClass)) 非常慢..
【解决方案3】:

在对 lambdas 进行进一步研究后,我发现它们会给我一个更优雅的解决方案,而且它不使用反射

所以我在我的列表定义中使用了

public delegate MyBaseType TypeCreator();

...
public TypeCreator Creator;

在我的函数调用中,一个简单而优雅的 lambda:

AddToList(()=>{return new MyType();});

我认为这比我的反射方法要干净得多,因为它允许将参数放入构造函数中,还有一些其他原因超出了这个问题的范围。 (它和我的项目很相配)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-21
    • 2017-01-31
    • 1970-01-01
    相关资源
    最近更新 更多