【问题标题】:Creating objects dynamically from Interface or assembly C#从接口或程序集 C# 动态创建对象
【发布时间】:2015-04-29 08:25:10
【问题描述】:

假设我有一些如下所示的界面

public interface IPerson
{
   Person GetPerson(string name);
   Person SetPerson(Person p);
}

我的 person 对象有一些嵌套对象,可能它继承自基类。

public class Person : SomeBaseClass
{
    public Name fullName {get;set;}
    // some other stuff
}

现在假设以上所有内容都编译为程序集(dll)。是否可以使用反射即时实例化 Person 对象?

void Main()
{
   Type type = typeof(IPerson);
   var instance = Activator.CreateInstace(t);
   // can't access properties of Person from instance.. :(
   // I wan't to populate all the properties of the object on the fly
   // but can't
 }

基本上我想引用 dll 或加载程序集动态迭代所述程序集中的所有对象,创建对象并填充它们的属性,最后对这些对象及其属性做一些事情。这可能吗?似乎我只有在进行静态转换时才能访问 Person.Name。

var oops = (Person)instance; // now I can access. but I dont want to have to cast!

【问题讨论】:

  • 但我不想强制转换 那么编译器如何知道实例是人还是动物?
  • SomeBaseClass 是否实现了IPerson 接口?
  • 您的Main 中的t 应该是什么?不能是type,因为你不能创建接口的实例。
  • 我猜你打错了。您无法实例化 IPerson,您可能打算将 typeof(Person) 传递给 Activator.CreateInstance
  • 当我们在做的时候,你为什么不简单地写var instance = (Person)Activator.CreateInstace(typeof(Person));

标签: c# .net reflection types activator


【解决方案1】:

从您的问题来看,尚不清楚您要创建的所有对象是否实现IPerson。如果他们这样做,那么乔恩兹明格的回答会很好。如果它们没有全部实现IPerson,您将不得不使用更多反射来获取属性集,找出每个属性的类型,然后采取行动。

var properties = instance.GetType().GetProperties();
foreach(var property in properties)
{
    var propertyType = property.PropertyType;

    if(propertyType == typeof(string))
    {
        property.SetValue(instance, "A String");
    }
    else if(propertyType == typeof(int))
    {
        property.SetValue(instance, 42);
    }
    // and so on for the different types
}

【讨论】:

    【解决方案2】:

    为了创建类型化实例,您可以使用Activator.CreateInstance<T>()。但是你需要传递一个具体的类型,而不是一个接口。所以,应该是

    Person instance = Activator.CreateInstance<Person>();
    

    如果你仍然需要能够使用接口,你可能应该使用一些DI容器先将IPerson接口映射到Person类(可以通过反射完成),然后使用容器解析一个实例IPerson.

    【讨论】:

      【解决方案3】:

      加载程序集。加载程序集后,您可以执行以下操作:

      foreach(var type in assembly.GetTypes())
      {
           //if the type implements IPerson, create it:
           if(typeof(type).GetInterfaces().Contains(typeof(IPerson))
           {
               var person = (IPerson)activator.CreateInstance(type);
      
               //now you can invoke IPerson methods on person
           }
      
      }
      

      这将使用默认构造函数为实现 IPerson 的程序集中的每种类型创建一个实例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-25
        • 2011-01-12
        • 2021-06-08
        • 2017-05-04
        • 2014-06-03
        • 2010-11-25
        • 1970-01-01
        相关资源
        最近更新 更多