为类型名创建泛型类

本文关键字:泛型类 创建 类型 | 更新日期: 2023-09-27 18:19:21

有一个类

public class Repository <TKey, TEntity>
{
    public ICollection<TEntity> Get()
    {
        using (var session = NHibernateHelper.OpenSession())
        {
            if (typeof(TEntity).IsAssignableFrom(typeof(IActualizable)))
                return session.CreateCriteria(typeof(TEntity)).Add(Restrictions.Lt("ActiveTo", DBService.GetServerTime())).List<TEntity>();
            return session.CreateCriteria(typeof(TEntity)).List<TEntity>();
        }
    }
}

如何创建它,只知道TEntity的名字?

的例子:

类游戏{}

string nameEntity = "Game";

var repository = new repository <长,> ? ?> ();

为类型名创建泛型类

这有三个部分:

  • 从字符串"Game"
  • 中获取Type创建泛型实例
  • 做一些有用的事情

第一个是相对简单,假设您了解更多—例如,Game位于特定的程序集和名称空间中。如果您知道该程序集中的某些固定类型,则可以使用:

Type type = typeof(SomeKnownType).Assembly
      .GetType("The.Namespace." + nameEntity);

(并检查它不返回null)

然后我们需要创建泛型类型:
object repo = Activator.CreateInstance(
      typeof(Repository<,>).MakeGenericType(new[] {typeof(long), type}));
但是,请注意这是object。如果有一个可以用于Repository<,>的非泛型接口或基类会更方便-我会把严肃的添加到一个!

要使用,这里最简单的方法是dynamic:

dynamic dynamicRepo = repo;
IList entities = dynamicRepo.Get();

,并使用非通用的IList API。如果dynamic不是一个选项,你必须使用反射。

或者,添加一个非泛型API将使这变得微不足道:

interface IRepository {
    IList Get();
}
public class Repository <TKey, TEntity> : IRepository {
    IList IRepository.Get() {
        return Get();
    }
    // your existing code here
}

那么它就是:

var repo = (IRepository)Activator.CreateInstance(
      typeof(Repository<,>).MakeGenericType(new[] {typeof(long), type}));
IList entities = repo.Get();

注意:根据数据的不同,IList可能无法工作-您可能需要切换到非通用的IEnumerable