为类型名称创建泛型类

时间:2013-06-20 07:05:01

标签: c# generics

有一个班级

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&lt;长, ??? &gt;();

1 个答案:

答案 0 :(得分:2)

这有三个部分:

  • 从字符串Type
  • 获取"Game"
  • 创建通用实例
  • 用它做一些有用的事

第一个是相对简单,假设你知道更多 - 例如,Game在特定的程序集和命名空间中。如果您知道该程序集中的某些 fixed 类型,则可以使用:

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