我的课程看起来像这样:
public RepositoryManager
{
public Type Context {get; private set;}
public RepositoryManager(Type context)
{
Context = context;
}
public IRepository<T> GetRepository<T>() where T : class
{
// create an instance of Context to pass to repo ctor
var contextInstance = Activator.CreateInstance(Context); // fail
return new Repository<T>(contextInstance);
}
}
我知道我需要将contextInstance
作为上下文的类型,但我不知道如何做到这一点。我无法做typeof(Context)
,因为编译器抱怨我使用了像'type'这样的属性(在这种情况下我的意图)。
如何将Context属性中存储的类型实例传递给Repository对象的构造函数?
更新/澄清
基于一些答案,我似乎没有清楚地解释自己。
我在Context属性中存储的类型很可能是DbContext的实现...例如由实体框架代码第一次逆向工程创建的SailingDbContext。它也可以是JudoDbContext。或者其他一些完全无关的背景。我不知道它可能是什么。但是,我做知道该类型可用于程序集。
存储库中的T将会出现POCO。也许客户或产品。我真的不知道,我也不在乎......我只知道它会存在。
Repository的构造函数需要传递Context属性中定义的类型的实例。这是我的问题。如何将Activator创建的对象强制转换为Context属性中定义的类型?
根据请求,我添加了Repository类的构造函数。但是,我担心这会使事情进一步混乱。我没有看到如何尝试将Activator创建的对象转换为对象的实例,以及实例传递给它的内容会影响对象的实例。
public class Repository<T> : IRepository<T>, IDisposable where T : class
{
private readonly DbSet<T> _dbSet;
public DbContext Context {get; set;}
public Repository()
{
// dont use ...
}
public Repository(DbContext context)
{
Context = context;
_dbSet = Context.Set<T>();
}
// lots more code snipped
}
请记住,这是IRepository接口的具体实现。将Activator创建的对象直接转换为类型DbContext并不是一个好的答案。
同样,我只是想将一个对象强制转换为Context属性中定义的类型。
答案 0 :(得分:3)
您需要使用“dynamic”而不是“var”来获得运行时动态创建的好处。 “var”解析/验证仍然在编译时发生。
dynamic contextInstance = Activator.CreateInstance(Context);
答案 1 :(得分:0)
您可以在MakeGenericType的帮助下动态创建泛型类型,然后简单地转换它:
public class RepositoryManager
{
public Type Context { get; private set; }
public RepositoryManager(Type context)
{
Context = context;
}
public IRepository<T> GetRepository<T>() where T : class
{
var contextInstance = Activator.CreateInstance(Context);
var repositoryType = typeof(Repository<>).MakeGenericType(Context);
var repository = Activator.CreateInstance(repositoryType, contextInstance);
return (IRepository<T>)repository;
}
}
答案 2 :(得分:0)
我建议你将UnitOfWork模式与Repository一起使用:
public class SqlRepository<T>: IRepository<T> where T: class, IEntity
{
protected readonly DbSet<T> _objectSet;
public SqlRepository(ApplicationDbContext context)
{
_objectSet = context.Set<T>();
}
}
和你的UnitOfWork类:
public class SqlUnitOfWork<T> : IUnitOfWork<T> where T : class, IEntity
{
private ApplicationDbContext _db;
public SqlUnitOfWork(ApplicationDbContext context)
{
_db = context;
}
public IRepository<T> Repistory
{
get
{
return new SqlRepository<T>(_db);
}
}
}
在asp.net mvc中有时你需要在同一个控制器上使用其他类型的存储库来进行测试 假设您需要在PersonController中查询帐户,然后在此模式中您可以轻松地在unitOfWork中编写类似的内容:
public IRepository<TEntity> GetTypeRepository<TEntity>() where TEntity : class, IEntity
{
return new SqlRepository<TEntity>(_db);
}
这样,每次需要新的存储库时,您都不需要实例化新的上下文。 我顺利接口定义了。 希望能帮助到你。 :)
答案 3 :(得分:0)
你试试这个吗?
var contextInstance = Activator.CreateInstance("YourAssemblyFullName", Context.FullName);