2017-03-31 52 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