使用反射实例化实现通用接口的类
本文关键字:接口 实现 反射 实例化 | 更新日期: 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
的实例。我不确定你会如何从Customer
到CustomerEntity
,但我相信你能解决这一部分。