2010-10-28 71 views
0

對象目前在代碼中,我使用的對象工廠返回我基於字符串的標籤,這已經切斷其目的直到現在的處理器。對象的工廠,創建需要依賴

using Core; 
using Data; 

public static class TagProcessorFactory 
{ 
public static ITagProcessor GetProcessor(string tag) 
{ 
    switch (tag) 
    { 
     case "gps0": 
     return new GpsTagProcessor(); 
     case "analog_manager": 
     return new AnalogManagerTagProcessor(); 
     case "input_manager": 
     return new InputManagerTagProcessor(); 
     case "j1939": 
     return new J1939TagProcessor(new MemcachedProvider(new[] { "localhost" }, "DigiGateway"), new PgnRepository()); 
     default: 
     return new UnknownTagProcessor(); 
    } 
} 
} 

長途區號

var processor = TagProcessorFactory.GetProcessor(tag.Name); 

if (!(processor is UnknownTagProcessor)) 
{ 
    var data = processor.Process(unitId, tag.Values); 

    Trace.WriteLine("Tag <{0}> processed. # of IO Items => {1}".FormatWith(tag.Name, data.Count())); 
} 

,你可以看到我的項目之一具有依賴性和IM試圖執行測試代碼,我想在模擬庫和高速緩存提供商能夠通過,但我似乎可以認爲一種方法來做到這一點。

這是一個不好的設計或任何人有任何想法解決它,使我廠可測試?

感謝

+1

是否有你決定不使用很多很多免費和優秀的依賴注入可用於C#的一個容器一些令人信服的理由?他們中的任何一個都可以優雅地處理這種注入模式 – anthony 2010-10-28 19:54:03

+0

我是。我使用autofac,我的問題是我不想傳入構建器/容器來解決依賴關係,iv讀取不通過容器。 – Waterboy4800 2010-10-28 19:57:48

+0

我會說傳遞一個工廠周圍是可以接受的,因爲這個類正在請求延遲創建一個對象。 – aqwert 2010-10-28 23:51:41

回答

3

由於您使用Autofac,你可以採取lookup relationship type的優勢:

public class Foo 
{ 
    private readonly IIndex<string, ITagProcessor> _tagProcessorIndex; 

    public Foo(IIndex<string, ITagProvider> tagProcessorIndex) 
    { 
     _tagProcessorIndex = tagProcessorIndex; 
    } 

    public void Process(int unitId, Tag tag) 
    { 
     ITagProcessor processor; 

     if(_tagProcessorIndex.TryGetValue(tag.Name, out processor)) 
     { 
      var data = processor.Process(unitId, tag.Values); 

      Trace.WriteLine("Tag <{0}> processed. # of IO Items => {1}".FormatWith(tag.Name, data.Count())); 
     } 
    } 
} 

更多信息,請參見TypedNamedAndKeysServices wiki article。要註冊不同的處理器,你會用它的鍵關聯的每個:

builder.RegisterType<GpsTagProcessor>().Keyed<ITagProcessor>("gps0"); 
builder.RegisterType<AnalogManagerTagProcessor>().Keyed<ITagProcessor>("analog_manager"); 
builder.RegisterType<InputManagerTagProcessor>().Keyed<ITagProcessor>("input_manager"); 

builder 
    .Register(c => new J1939TagProcessor(new MemcachedProvider(new[] { "localhost" }, new PgnRepository())) 
    .Keyed<ITagProcessor>("j1939"); 

注意我們不註冊UnknownTagProcessor。這是工廠主叫方的一個信號,表示沒有找到處理器,我們用TryGetValue代替。

+0

我喜歡這種方法。只想我不知道如何解決從構建器的IIndex <字符串ITagProvider>傳遞到Foo的構造函數。幫幫我? – Waterboy4800 2010-10-29 19:36:04

+0

Autofac的關係類型是自動的。如果你只是調用'c.Resolve >()',容器就會解釋這個請求併爲你創建適當的實現。即使使用'builder.RegisterType ()'也是如此。再例如,如果您接受'Func ',容器將識別關係類型並生成解析'SomeType'的函數。它非常漂亮。 – 2010-10-29 20:25:51

+0

很酷。非常感謝! – Waterboy4800 2010-10-29 20:42:31

0

我建議你通過another SO post看。它一次解決了幾個問題,包括如何替換構造函數值 - 而不是一團糟。具體來說,構造函數的參數只是成爲「Context」類的靜態字段,由內部類的構造函數讀取。