2017-03-31 33 views
0

我使用SimpleInjector作为我的C#WinForms应用程序。 我需要在运行时决定要访问哪个存储库(Oracle或SqlServer),因为这取决于用户要连接到哪个数据库。 目前我是这样做的,只要我为存储库添加装饰器就会失败。如何使用数据库特定的存储库

_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()); 
} 
+0

库如何选择?用户在应用程序运行时是否从一个数据库更改为另一个数据库,或者在启动期间是否确定一次(例如,通过在配置文件中指定)? – Steven

+0

是的,它正在运行。用户可以选择在Oracle上运行一个分析,在SqlServer上运行下一个分析,而不必重新启动应用程序。 – user213360

+0

此外,处理的数据格式相同。 oracle或sqlserver数据由相应的存储库放入业务实体中,以供业务层进一步处理。 @Steven任何更新这个额外的信息? – user213360

回答

1

你的问题实际上是不容易回答。

而且我的胃告诉我,依赖于上面显示的类型的字符串名称是不正确的。这应该如何正确完成?

以您目前的设计,我可以想像,改变你的RepoProvider实施这样的事情:

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) }, 
    }); 

这样您就可以申请装修:

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(); 
} 

您可以按如下所示注册此,而不会破坏系统。

+1

感谢您的答案。就像在你的博客或者你的博客上多次提供你的答案一样,这就像打开了通向另一个世界的大门;-) – user213360

+0

由于你试图将装饰器应用到你的版本库,你可能想阅读[这篇博客文章]( HTTPS://www.cuttingedge。它/ blogs/steven/pivot/entry.php?id = 92)讨论了特定于实体的存储库抽象可能是一件坏事,以及它们如何阻碍你有效地使用装饰器应用横切关注点。 – Steven

相关问题