我有一个函数,它在运行时创建多个表的存储库字典,我想要的是使它成为通用的,但我仍然坚持这个错误..
public IRepository<TEntity> GetRepository<TEntity>(string TypeName) where TEntity : class
{
Type t = GetInstance(TypeName);
if (_repositories.Keys.Contains(t))
{
return _repositories[t] as IRepository<TEntity>;
}
var repository = new Repository<TEntity>(_context);
_repositories.Add(t, repository);
return repository;
}
当我将此功能称为
时 string tn = tt.GetType().FullName;
Type tttt = GetInstance(tn);
uu.GetRepository<Object>(tn).Add(tt);
它抛出Exception
实体类型Object不是当前上下文的模型的一部分。
我怎样才能实现这一目标
string tn = tt.GetType().FullName;
Type tttt = GetInstance(tn);
uu.GetRepository<typeof(tt)>(tn).Add(tt);
或其他类型的东西。
答案 0 :(得分:1)
如果您希望它是通用的,则需要将类型指定为通用参数。 客户端代码必须知道类型,而不仅仅是具有该类型的实例。
在您的情况下,使用Object
作为泛型类型参数没有意义,因为这不会为底层框架提供类型推断。这就是抛出异常的原因。
此外,在运行时,如果您的解决方案是多线程的,则无法在没有额外同步的情况下使用Dictionary。对于您的任务,我建议使用ConcurrentDictionary。
void Main()
{
var repository = GetRepository<MyEntity1>();
MyEntity1 instance = repository.Get(1);
}
class MyEntity1
{
}
ConcurrentDictionary<Type, object> repositories = new ConcurrentDictionary<System.Type, object>();
interface IRepository<T>
{
T Get(int id);
}
class Repository<T> : IRepository<T> where T:new()
{
public T Get(int id)
{
return new T();
}
}
IRepository<T> GetRepository<T>() where T:new()
{
return (IRepository<T>)repositories.GetOrAdd(typeof(T), t => new Repository<T>());
}
答案 1 :(得分:1)
如果您只是想知道原则上该如何做(如果忽略了有关您是否应该这样做的问题),那么这是如何:
string tn = tt.GetType().FullName;
// get reference to GetRepository<TEntity>
var genericGet = uu.GetType().GetMethod("GetRepository").MakeGenericMethod(tt.GetType());
// invoke to get IRepository<TEntity>
var repository = genericGet.Invoke(uu, new object[] { tn});
// get IRepository<TEntity>.Add
var addMethod = repository.GetType().GetMethod("Add");
// invoke
addMethod.Invoke(repository, new object[] { tt});
如果你这样做 - 最好让你的Add
方法接受对象而不是泛型类型参数,这样使你的界面只是IRepository
,而不是IRepository<T>
。然后在内部存储库中 - 使用上面的技术获取对特定DbSet
和Add
方法的引用。