如何使用数据库特定的存储库

时间:2017-03-31 13:28:39

标签: c# simple-injector

我在我的C#WinForms应用程序中使用SimpleInjector。 我需要在运行时决定访问哪个存储库(Oracle或SqlServer),因为这取决于他想要连接到哪个数据库的用户。 目前我这样做了,一旦我为存储库添加了一个Decorator就会失败。

_container.RegisterCollection<IRepository>(
    new[] { typeof(OraRepository), typeof(SqlRepository) });

并且为了区分使用哪一个,我使用这样的提供者类:

    public T GetRepo<T>(bool oracle)
        where T : class
    {
        var instances = _container.GetAllInstances<T>();
        if (oracle)
        {
            return instances.First(i => i.GetType().Name.StartsWith("Ora"));
        }
        else
        {
            return instances.First(i => !i.GetType().Name.StartsWith("Ora"));
        }
    }

我不想为每个数据库添加装饰器。此外,似乎不可能,因为没有RegisterDecoratorCollection; - )

我的肚子告诉我,依靠上面所示类型的字符串名称是不对的。 该如何正确完成?

编辑:
有关使用场景的更多高级信息:

我的单位测试:

[TestInitialize()]
public void MyTestInitialize()
{
    var container = new SimpleInjector.Container();
    ... other dependencies ...
    container.RegisterCollection<ICarRepository>(
      new[] { typeof(OraCarRepository), typeof(SqlCarRepository) });
    container.RegisterCollection<ITruckRepository>(
      new[] { typeof(OraTruckRepository), typeof(SqlTruckRepository) });
    _provider = new RepoProvider(container);
}

运行测试:

[TestMethod()]
public void GetRepoTest()
{
    var repo = _provider.GetRepo<ICarRepository>(true);
    Assert.AreEqual(typeof(OraCarRepository), repo.GetType());

    repo = _provider.GetRepo<ICarRepository>(false);
    Assert.AreEqual(typeof(SqlCarRepository), repo.GetType());

    var repo2 = _provider.GetRepo<ITruckRepository>(true);
    Assert.AreEqual(typeof(OraTruckRepository), repo2.GetType());

    repo2 = _provider.GetRepo<ITruckRepository>(false);
    Assert.AreEqual(typeof(SqlTruckRepository), repo2.GetType());
}

1 个答案:

答案 0 :(得分:1)

您的问题实际上并不容易回答。

  

我的肚子告诉我,依靠上面所示类型的字符串名称是不对的。该如何正确完成?

根据您当前的设计,我可以想象将您的RepoProvider实现更改为以下内容:

private Dictionary<Type, InstanceProducer> oracle;
private Dictionary<Type, InstanceProducer> sql;

public RepoProvider(
    Dictionary<Type, InstanceProducer> oracle, 
    Dictionary<Type, InstanceProducer> sql)
{
    this.oracle = oracle;
    this.sql = sql;
}

public T GetRepo<T>(bool oracle)  where T : class
{
    Dictionary<Type, InstanceProducer> repos = oracle ? this.oracle : this.sql;
    return (T)repos[typeof(T)].GetInstance();
}

您可以按如下方式注册:

container.RegisterSingleton<IRepoProvider>(new RepoProvider(
    oracle: new Dictionary<Type, InstanceProducer>
    {
        { typeof(ICarRepository), Lifestyle.Transient.CreateProducer<ICarRepository, OraCarRepository>(container) },
        { typeof(ITruckRepository), Lifestyle.Transient.CreateProducer<ITruckRepository, OraTruckRepository>(container) },
    },
    sql: new Dictionary<Type, InstanceProducer>
    {
        { typeof(ICarRepository), Lifestyle.Transient.CreateProducer<ICarRepository, SqlCarRepository>(container) },
        { typeof(ITruckRepository), Lifestyle.Transient.CreateProducer<ITruckRepository, SqlTruckRepository>(container) },
    });

这允许您在不破坏系统的情况下应用装饰器。