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

本文关键字:接口 实现 反射 实例化 | 更新日期: 2023-09-27 17:59:36

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

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>

感谢

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

您需要以某种方式构造完整的类型名称,以便获得代表该类型的Type实例。您可能会决定类型名称依赖于一个约定,这样您就可以找到完整的类型名称:

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

然后就是调用Activator.CreateInstance的问题,如您所见。

然而,我强烈建议您考虑使用IoC框架来解决这个问题。

回复:您的评论:

您不能将CustomerEntityManager强制转换为IEntityManager,因为它不是这样实现的——它只实现了IEntityManager。如果允许强制转换,则类型安全性将被破坏(当实现明确期望客户时,您可以传入业务实体,或者,至少合同中是这样说的。(Co/contro差异不能在这里保存您,因为t同时传入和传出IEntityManager)。

忘记自己使用低级反射,这是一项非常不方便的工作。如果可以的话,可以使用IoC框架,即StructureMap。使用StructureMap,您只需要创建一个知道所有依赖项的注册表(例如CustomersEntityManager是我们对IEntityManager<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

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

结账Activator.CreateInstance()

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

将为您提供一个Customer的实例。我不确定你会如何从CustomerCustomerEntity,但我相信你能解决这一部分。