我已经实现了一个通用存储库,但是要求在运行时动态创建适当的存储库,并将实体类型作为字符串。
我已设法使用以下方法创建存储库:
Assembly common = Assembly.LoadFrom(@"CommonLibrary.dll");
Type entityType = common.GetType("Models.OneOfManyEntities");
Type repoType = typeof(TradeSiftRepository<>).MakeGenericType(entityType);
var repo = Activator.CreateInstance(repoType, new UnitOfWork());
但是repo
是一个对象,我真的希望它转换为IRepository<TEntity>
我尝试了IRepository<entityType>
但是这不正确
这是repo的界面:
public interface IRepository<TEntity> : IDisposable where TEntity : class
{
IQueryable<TEntity> FindAll();
IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "");
TEntity FindById(object Id);
void Insert(TEntity entity);
void Update(TEntity entity);
void Delete(object id);
void Delete(TEntity entity);
}
repo的激活实例类型正确,但Activator返回一个对象类型,所以我需要将其强制转换为使用方法。
答案 0 :(得分:1)
您说要将对象强制转换为IRepository<TEntity>
,但TEntity
仅在运行时可用(您在Type
变量中引用了entityType
对象)。
如果可能IRepository<entityType>
,您希望从FindById
等方法中获得什么?我认为可能是一个entityType
个实例?现在,由于entityType
可以是任何类型,并且仅在运行时确定,编译器可能不知道如何编译涉及entityType
变量的任何代码。因此,IRepository<entityType>
是不可能的。
有两种可能的解决方案,具体取决于您希望实现的目标:
IRepository
- 类似于处理object
类型实体的接口(并且可能会抛出ArgumentException
如果添加的任何内容与当前entityType
不匹配,则返回s。将Activator.CreateInstance
调用的结果转换为新的接口类型。Activator.CreateInstance
实例化该通用类,与您现在使用TradeSiftRepository<T>
类直接实现的类似。答案 1 :(得分:0)
我不认为你问的是可能的。如果您的代码正在接收表示泛型类型参数的字符串,则它所代表的类型只能在运行时确定。但是,应在编译时指定泛型类型参数。
如果您想将它作为返回类型的类型参数使用,我认为您必须接收实体类型作为泛型类型参数:
public IRepository<TEntity> MakeRepository<TEntity>() where TEntity : class
{
var repo = new TradeSiftRepository<TEntity>(new UnitOfWork());
return repo;
}
IRepository<User> userRepository = MakeRepository<User>();
如果你肯定想要将实体类型名称作为字符串接收,那么在编译时将结果转换为实际类型的责任应该通过调用代码来完成,因为调用代码是指定类型的:
public object MakeRepository(string entityTypeName)
{
Assembly common = Assembly.LoadFrom(@"CommonLibrary.dll");
Type entityType = common.GetType(entityTypeName);
Type repoType = typeof(TradeSiftRepository<>).MakeGenericType(entityType);
var repo = Activator.CreateInstance(repoType, new UnitOfWork());
return repo;
}
IRepository<User> userRepository = (IRepository<User>)MakeRepository("User");
但是,通过使用该方法的通用版本可以简化上述代码;重复较少。如果调用代码也不知道它要求的类型,我认为你没有选择。
一种可能的解决方法是返回动态类型,这将使调用代码假定它具有其作者想要的类型的对象:
public dynamic MakeRepository(string entityTypeName)
{
Assembly common = Assembly.LoadFrom(@"CommonLibrary.dll");
Type entityType = common.GetType(entityTypeName);
Type repoType = typeof(TradeSiftRepository<>).MakeGenericType(entityType);
var repo = Activator.CreateInstance(repoType, new UnitOfWork());
return repo;
}
dynamic userRepository = MakeRepository("ConsoleApplication1.User");
User user = userRepository.FindById(1);