C# 将函数的泛型类型设为泛型对象

C# 将函数的泛型类型设为泛型对象,c#,generics,reflection,C#,Generics,Reflection,我有一个函数,它可以在运行时生成多个表的存储库字典,我想要的是将其作为泛型,但是我被这个错误卡住了 public IRepository<TEntity> GetRepository<TEntity>(string TypeName) where TEntity : class { Type t = GetInstance(TypeName); if (_repositories.Keys.Contains(t))

我有一个函数,它可以在运行时生成多个表的存储库字典,我想要的是将其作为泛型,但是我被这个错误卡住了

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

或者其他类型。

如果希望它是泛型的,则需要指定一个类型作为泛型参数。 客户机代码必须知道该类型,而不仅仅是该类型的实例

在您的例子中,使用
Object
作为泛型类型参数是没有意义的,因为这不会为底层框架提供类型推断。这就是引发异常的原因

另外,在运行时,如果您的解决方案是多线程的,那么如果没有额外的同步,您就不能使用字典。对于你的任务,我推荐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>());
}
void Main()
{
var repository=GetRepository();
MyEntity1实例=repository.Get(1);
}
MyEntity1类
{
}
ConcurrentDictionary存储库=新建ConcurrentDictionary();
界面假定
{
T Get(int-id);
}
类存储库:IRepository,其中T:new()
{
公共T获取(int id)
{
返回新的T();
}
}
IRepository GetRepository(),其中T:new()
{
return(IRepository)repositories.GetOrAdd(typeof(T),T=>newrepository());
}

如果您只是想知道原则上如何做(如果忽略关于您是否应该这样做的问题),那么下面是如何做的:

 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});
string tn=tt.GetType().FullName;
//获取对GetRepository的引用
var genericGet=uu.GetType().GetMethod(“GetRepository”).MakeGenericMethod(tt.GetType());
//调用以获取IRepository
var repository=genericGet.Invoke(uu,新对象[]{tn});
//获取IRepository。添加
var addMethod=repository.GetType().GetMethod(“添加”);
//援引
Invoke(存储库,新对象[]{tt});

如果您愿意这样做,那么最好让您的
Add
方法接受对象而不是泛型类型参数,这样您的接口就只接受
IRepository
,而不是
IRepository
。然后在存储库内部-使用上述技术获取对特定
DbSet
Add
方法的引用。

您可以通过反射来实现,但这有什么意义呢?然后,它将忽略泛型类型参数的所有好处。你为什么要这样做?你初始化函数“uu”吗?你在使用实体框架?@Evk我有一个场景,每次我想保存和更新时,都会通过它动态删除所有动态创建的记录。@LinhTuan,是的,我初始化uu是的,这是工作,但如果有其他解决方案吗?@user6002727,我记得,实体框架上下文具有非类型化的数据库集。比如context.Set(typeof(yourtentity))。您可以使用这些集合(同样,您的IRepository将没有泛型参数)。。那样
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>());
}
 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});