从Interface或程序集C#动态创建对象

时间:2015-02-26 19:38:26

标签: c# .net reflection types activator

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

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!

3 个答案:

答案 0 :(得分:2)

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

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的每个类型的实例。

答案 1 :(得分:1)

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

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

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

的实例

答案 2 :(得分:0)

根据您的问题,您不清楚您要创建的所有对象是否实现IPerson。如果他们这样做,那么Joe Enzminger的回答将会很有效。如果他们没有全部实施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
}