2012-02-22 69 views
8

如果我有一個類,這對同類型的雙重依賴(需要兩種不同的情況下),如果實例之間唯一的區別是一個更深層次的依賴性,什麼是對的最佳途徑Ninject是否執行DI並將兩個圖分開?Ninject:注射相同類型的兩個不同的對象

實例對象圖:

foo → ClassA → ClassB 
bar → ClassA → ClassB 

C的類的構造函數:

public class C 
{ 
    public C(ClassB foo, ClassB bar) { … } 
} 

那麼,如何確保與foo實例化的ClassB作爲ClassB扶養被提供foobar… bar

只是爲了一些背景,我有一些需求的變化,所以我需要一個複合只寫庫

public class CompositeWriteRepository<T> : IAdd<T> 
{ 
    public CompositeWriteRepository(IAdd<T> foo, IAdd<T> bar, Func<T, bool> descriminator) { ... } 
    public Add(T entity) 
    { 
     if (descriminator(entity)) { 
      foo.Add(entity); 
     } else { 
      bar.Add(entity); 
     } 
    }   
} 

隨着嘲諷更換隻寫庫(IADD),這是很容易,我可以使用名稱注入:

kernel.Bind<IAdd<EntityType>>().To<fooRepository>().Named("foo"); 
kernel.Bind<IAdd<EntityType>>().To<barRepository>().Named("bar"); 

kernel.Bind<IAdd<EntityType>>().To<CompositeWriterRepository<EntityType>>() 
    .WithConstructorArgument("foo", x => x.Kernel.Get<IAdd<EntityType>>("foo") 
    .WithConstructorArgument("bar", x => x.Kernel.Get<IAdd<EntityType>>("bar"); 

問題出在我使用真實存儲庫時; foobar最終寫入文件,以便它們需要不同的文件名。由於它們是StreamWriter存儲庫,它們的一個依賴項實際上獲取了兩個不同的文件名。

string FileName → FileStreamWriterFactory → StreamRepository → CompositeRepository 

我發現迄今建造的東西,唯一的辦法就是讓一個名爲FileName,名爲FileStreamWriterFactory,命名爲StreamRepository × 2(一次foo和一次bar)。這好像很多的工作,所以我希望有更好的解決方案。

,如果需要,我可以重新設計,感覺就像一個優雅的方式來迅速分離該條目時要求更改添加。我意識到我的課都是很具體,但我認爲單一職責一般會支持這一點,在我的情況下,我們寫了一堆的小應用程序,並擁有了更多的要求,我們可以實現這樣的一個好辦法,具有可重複使用的代碼,很多的圍繞這一點,我基本上只需要重新配置不同的任務。

解決方案
Remo Gloor應該得到信用;他可能是最好的做法。

我實際上做的就是創建一個新的擴展

public static bool WhenAnchester(this IRequest request, Func<IRequest, bool> conditions) 
{ 
    var parentContext = request.ParentContext; 
    if (parentContext == null) { 
      return false; 
    } 

    return conditions(parentContext.Request) || 
     parentContext.Request.WhenAnchester(conditions); 
} 

這就讓我輕鬆地控制文件中獲取注入到存儲庫。

kernel.Bind<string>().ToConstant("Foo.txt") 
    .When(x => x.Target.Name == "filepath" && 
       x.WhenAnchester(t => t.Target != null && t.Target.Name == "Dest1")); 

kernel.Bind<string>().ToConstant("Bar.txt") 
    .When(x => x.Target.Name == "filepath" && 
       x.WhenAnchester(t => t.Target != null && t.Target.Name == "Dest2")); 

有可能是一個更好的解決方案,所以我不會推薦這個給別人,但它的工作對我很好。

+1

DI容器應該解除特定實現的依賴關係,因此這些類只依賴於接口。而你想要的是相反的,我們試圖避免遵循IoC的想法。 – zerkms 2012-02-22 23:08:59

+0

我交換了另一個IAdd的一個實現,我這樣做只是寫一個新類(複合IAdd)並更改我的合成根。誠然,它不是一個非常強烈的指示我正在使用DI,但這似乎不像一個代碼嗅到我。複雜性實際上是因爲我的類不關心,所以我最終得到兩個非常相似的依賴關係圖,而且我的構圖需要關心(應該),因爲業務需求是如此。我可以引入兩種新的區分類型,它可能更清晰,但也更多變化。 – 2012-02-22 23:19:42

回答

相關問題