使用反射实例化实现通用接口的类

时间:2011-06-20 20:27:31

标签: c# reflection

我在业务逻辑程序集中有以下内容:

public class BusinessEntity
{
    ...
}

public class Customer : BusinessEntity
{
    ...
}

public interface IEntityManager <T> where T : BusinessEntity
{
    T SaveData(T oData);
}

public CustomerEntityManager : IEntityManager <Customer>
{
    Customer SaveData(Customer o)
    {
        ...
    }
}

我被迫通过反射和实例化CustomersEntityManager在我当前的项目中加载上面的程序集(由于一些显而易见的原因)。想象一下,我正在编写如下方法:

public class EntityFactory
{
  public static IEntityManager<BusinessEntity> GetManagerInstance(string EntityName)
  {
     var asm = GetAssembly(); // imagine that I loaded the assembly somehow
     EntityName = "Customer"; // just imagine
     object o;     
     // DO NOT KNOW WHAT TO WRITE HERE.
     return o as IEntityManager<BusinessEntity>; // this needs to be an instance of CustomerEntityManager.
  }
}

我可以选择修改业务程序集。但实例创建需要在我当前的项目中,我必须使用反射加载业务程序集。所有数据类型仅在运行时才知道。

我可能会遗漏一些基本的东西,或者可能是错误的编码。请帮我解决这个问题。

更新:

遵循“driss”建议,如下:

string fullTypeName = "Your.Namespace." + EntityName + "EntityManager";
object o = Activator.CreateInstance(asm.FullName, fullTypeName);

看起来它创建了实例。但是,最终出现了错误:

  

无法将'o'(实际类型为'CustomerEntityManager')转换为'IEntityManager'

执行以下语句时:

return o as IEntityManager<BusinessEntity>

由于

3 个答案:

答案 0 :(得分:3)

您需要以某种方式构造完整的类型名称,以便您可以获得表示该类型的Type实例。您可能认为类型名称依赖于约定,因此您可以找到完整的类型名称:

string fullTypeName = "Your.Namespace." + EntityName + "EntityManager";
object o = Activator.CreateInstance(asm.FullName, fullTypeName);

然后,只需调用Activator.CreateInstance,就像你看到的那样。

但是,我强烈建议您考虑使用IoC框架来解决此问题。

回复:您的评论:

您不能将CustomerEntityManager转换为IEntityManager,因为它不是它实现的 - 它只实现IEntityManager。如果允许演员表,那么类型安全将被打破(当实施明确期望客户,或者至少是合同所说的那样时,您可以传递BusinessEntity。(Co / contra方差可以挽救您)这里因为T进出IEntityManager)。

答案 1 :(得分:1)

忘记使用自己的低级反射,很多不太方便的工作。如果可以,请使用IoC框架,即StructureMap。使用StructureMap,您只需要创建一个知道所有依赖项的注册表(例如CustomersEntityManagerIEntityManager<Customer>的实现)。它看起来更像是:

For<IEntityManager<Customer>>().Use<CustomersEntityManager>()

现在,如果您向StructureMap容器​​询问IEntityManager<Customer>的实现,那么您将获得CustomersEntityManager

ObjectFactory.GetInstance<IEntityManager<Customer>>(); // will return instance of CustomersEntityManager

如果在编译时不知道请求的类型,可以使用普通Type实例请求实体管理器:

string entityName = "Customer";
Type entityType = Type.GetType(entityType);
Type requestedType = typeof(IEntityManager<>).MakeGenericType(new[] { entityType });
ObjectFactory.GetInstance(requestedType); // will also return CustomersEntityManager instance

可以在程序集中定义注册表,而无需触及业务程序集。

答案 2 :(得分:0)

结帐Activator.CreateInstance()

Object o = Activator.CreateInstance (asm.FullName, EntityName );

会为您提供Customer的实例。我不确定你会如何从Customer转到CustomerEntity,但我相信你可以解决这个问题。