2010-10-28 73 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”类的静态字段,由内部类的构造函数读取。