На этот вопрос уже есть ответ здесь:
У меня проблемы с созданием нового экземпляра класса по типу с дженериком. Я пытаюсь создать контекст базы данных, который можно создать либо с помощью DBSet, либо с помощью FakeDBSet. FakeDBSet будет использоваться в тестовом коде. В настоящее время у меня есть полный фальшивый контекст данных, но это пустая трата времени, поскольку единственная реальная разница заключается в используемом DBSet. Я безуспешно изучал использование Activator.CreateInstance().
Пример:
public class Album {}
public class Artist {}
public class MusicStoreContext
{
public IDbSet Albums { get; set; }
public IDbSet Artists { get; set; }
public MusicStoreContext(Type dbSetType)
{
Albums = new (dbSetType);
Artists = new (dbSetType);
}
}
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 where T : IDBSet
{
public IDbSet Albums { get; set; }
public IDbSet Artists { get; set; }
...
Вот что я придумал, что работает благодаря предложению Джона:
public class MusicStoreContext
{
private IDbSet _Albums;
private IDbSet _Artists;
public IDbSet Albums { get {return _Albums;} }
public IDbSet Artists { get {return _Artists; }
public MusicStoreContext(Type dbSetType)
{
Albums = new (dbSetType);
Artists = new (dbSetType);
}
public TaxDocumentsContext() : base()
{
CreateDbSets(new ProductionDbSetProvider());
}
public TaxDocumentsContext(IDbSetProvider provider)
{
CreateDbSets(provider);
}
private void CreateDbSets(IDbSetProvider provider)
{
provider.CreateDbSet(this, ref _Albums);
provider.CreateDbSet(this, ref _Artists);
}
}
И для DbSetProvider:
public interface IDbSetProvider
{
void CreateDbSet(DbContext context, ref IDbSet dbSet) where T : class;
}
public class FakeDbSetProvider : IDbSetProvider
{
public void CreateDbSet(DbContext context, ref IDbSet dbSet) where T : class
{
dbSet = new FakeDbSet();
}
}
public class ProductionDbSetProvider : IDbSetProvider
{
public void CreateDbSet(DbContext context, ref IDbSet dbSet) where T : class
{
dbSet = context.Set();
}
}
Теперь я могу легко протестируйте, не затрагивая БД, используя FakeDbSet отсюда: http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/