对象工厂,用于创建需要依赖项的对象

时间:2010-10-28 19:50:34

标签: c# design-patterns dependency-injection factory-pattern

目前在代码中我使用了一个对象工厂来返回一个基于字符串标签的处理器,这个处理器到目前为止已经切断了它的目的。

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

你可以看到我的一个项目有依赖关系,我试图执行测试代码,我想传递模拟存储库和缓存提供程序,但我似乎想到了一种方法来做到这一点。

这是一个糟糕的设计还是有人有任何想法来修复它以使我的工厂可测试?

由于

3 个答案:

答案 0 :(得分: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表示。

答案 1 :(得分:0)

使用像StructureMap这样的东西你可以使用ObjectFactory,它在配置时会返回一个命名的具体实例。

http://structuremap.net/structuremap/index.html

答案 2 :(得分:0)

我建议你浏览another SO post。它同时解决了几个问题,包括如何替换构造函数值 - 没有一团糟。具体来说,构造函数的参数只是“Context”类的静态字段,由内部类的构造函数读取。