Как создать экземпляр класса по типу с помощью универсального [дубликата]

На этот вопрос уже есть ответ здесь:

У меня проблемы с созданием нового экземпляра класса по типу с дженериком. Я пытаюсь создать контекст базы данных, который можно создать либо с помощью 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/

0
задан Bruce C 1 June 2012 в 21:18
поделиться