将泛型类型设置为通用对象

时间:2016-05-11 07:56:56

标签: c# generics reflection

我有一个函数,它在运行时创建多个表的存储库字典,我想要的是使它成为通用的,但我仍然坚持这个错误..

 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);

或其他类型的东西。

2 个答案:

答案 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>。然后在内部存储库中 - 使用上面的技术获取对特定DbSetAdd方法的引用。