我在使用泛型创建类的新实例时遇到问题。我想要做的是拥有一个可以使用DBSet<>创建的数据库上下文。或者是FakeDBSet<>。 FakeDBSet将用于测试代码。我目前有一个完整的假数据文本,但它是一个浪费,因为唯一真正的区别是使用的DBSet。我已经研究过使用Activator.CreateInstance()而没有太多运气。
示例:
public class Album {}
public class Artist {}
public class MusicStoreContext
{
public IDbSet<Album> Albums { get; set; }
public IDbSet<Artist> Artists { get; set; }
public MusicStoreContext(Type dbSetType)
{
Albums = new (dbSetType)<Album>;
Artists = new (dbSetType)<Artist>;
}
}
public class Startup
{
public Startup()
{
// Production code would do something like this:
MusicStoreContext context = new MusicStoreContext(typeof(DbSet<>));
// Test code would do something like this:
MusicStoreContext testContext = new MusicStoreContext(typeof(FakeDbSet<>));
}
}
我也尝试过这样的事情:
public class MusicStoreContext<T> where T : IDBSet
{
public IDbSet<Album> Albums { get; set; }
public IDbSet<Artist> Artists { get; set; }
...
感谢Jon的建议,以下是我提出的建议:
public class MusicStoreContext
{
private IDbSet<Album> _Albums;
private IDbSet<Artist> _Artists;
public IDbSet<Album> Albums { get {return _Albums;} }
public IDbSet<Artist> Artists { get {return _Artists; }
public MusicStoreContext(Type dbSetType)
{
Albums = new (dbSetType)<Album>;
Artists = new (dbSetType)<Artist>;
}
public TaxDocumentsContext() : base()
{
CreateDbSets(new ProductionDbSetProvider());
}
public TaxDocumentsContext(IDbSetProvider provider)
{
CreateDbSets(provider);
}
private void CreateDbSets(IDbSetProvider provider)
{
provider.CreateDbSet<Album>(this, ref _Albums);
provider.CreateDbSet<Artist>(this, ref _Artists);
}
}
对于DbSetProvider:
public interface IDbSetProvider
{
void CreateDbSet<T>(DbContext context, ref IDbSet<T> dbSet) where T : class;
}
public class FakeDbSetProvider : IDbSetProvider
{
public void CreateDbSet<T>(DbContext context, ref IDbSet<T> dbSet) where T : class
{
dbSet = new FakeDbSet<T>();
}
}
public class ProductionDbSetProvider : IDbSetProvider
{
public void CreateDbSet<T>(DbContext context, ref IDbSet<T> dbSet) where T : class
{
dbSet = context.Set<T>();
}
}
现在我可以轻松测试而无需使用FakeDbSet从此处访问数据库: http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/
答案 0 :(得分:6)
编辑:如果有问题的集合有适当的构造函数,您可以使用Type.MakeGenericType
创建相关的构造类型,并使用Activator.CreateInstance
调用构造函数:
Type albumType = dbSetType.MakeGenericType(typeof(Album));
Albums = (IDbSet<Album>) Activator.CreateInstance(albumType);
或者,您可以传入具有通用方法的DbSetProvider
(或其他):
public IDbSet<T> CreateDbSet<T>()
然后你有一个ProductionDbSetProvider
和一个FakeDbSetProvider
:
public MusicStoreContext(DbSetProvider provider)
{
Albums = provider.CreateDbSet<Album>();
Artists = provider.CreateDbSet<Artist>();
}
个人觉得我觉得更干净,但YMMV。