1

有一堂课

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 的名称?

例子:

类游戏{}

字符串名称实体 = “游戏”;

var repository = new Repository< long, ??? >();

4

1 回答 1

2

这包括三个部分:

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

第一个相对容易,假设您了解更多 - 例如,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();

并使用非通用IListAPI。如果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

于 2013-06-20T07:18:13.433 回答