使用StructureMap注入相应的实现

时间:2013-08-05 16:37:32

标签: c# .net ioc-container structuremap

我有一个具有以下结构的课程

class Measure
{
    public MeasureType measureType { get; set; }
    public readonly IMeasureService _service ;

    public Measure(IMeasureService service)
    {
        _service = service;
    }
    public Calculate()
    {
        _service.Calculate(this);
    }
}

所以我对不同的measureTypes有不同的MeasureService实现。是否可以使用StructureMap根据measureType注入相应的MeasureService。

MeasureType只是一个枚举类型,在整个实例中永远不会被更改。

1 个答案:

答案 0 :(得分:2)

由于一个简单的原因,无法指示StructureMap这样做:

  • 在创建实例时,无法设置measureType属性。
  • 您无法在以后设置IMeasureService依赖关系,因为它是readonly(也应该是private

因此,这个问题的解决方案更多地与类的设计有关,而不是与StructureMap有关。

以下是我在这种情况下通常会选择的解决方案:


1)将选择正确IMeasureService实施的任务委托给不同的组件。

例如,该组件可以被称为MeasureServiceFactory并具有以下实现:

public class MeasureServiceFactory
{
    private readonly Func<MeasureServiceType1> _type1Service;
    private readonly Func<MeasureServiceType2> _type2Service;

    public MeasureServiceFactory(
        Func<MeasureServiceType1> type1Service,
        Func<MeasureServiceType2> type2Service)
    {
        _type1Service = type1Service;
        _type2Service = type2Service;
    }

    public IMeasureService GetServiceForType(MeasureType type)
    {
        switch (type)
        {
            case MeasureType.Type1:
                return _type1Service();
            case MeasureType.Type2:
                return _type2Service();
            default:
                throw new ApplicationException("Unexpected measure type!");
        }
    }
}

请注意,StructureMap会自动注入两个Func,并对容器的GetInstance()方法进行适当调用,以便正确解析所需的服务。

现在,Measure类将不再具有直接IMeasureService依赖关系,而是取决于工厂:

public class Measure
{
    public MeasureType measureType { get; set; }
    private readonly MeasureServiceFactory _measureServiceFactory;

    public Measure(MeasureServiceFactory measureServiceFactory)
    {
        _measureServiceFactory = measureServiceFactory;
    }

    public void Calculate()
    {
        var service = _measureServiceFactory.GetServiceForType(measureType);
        service.Calculate(this);
    }
}

请注意,不需要StructureMap配置。容器将能够正确解决所有问题。


2)为了保持Measure类不受影响,您可以使MeasureServiceFactory实现IMeasureService接口:

public class MeasureServiceFactory : IMeasureService
{
    private readonly Func<MeasureServiceType1> _type1Service;
    private readonly Func<MeasureServiceType2> _type2Service;

    public MeasureServiceFactory(
        Func<MeasureServiceType1> type1Service,
        Func<MeasureServiceType2> type2Service)
    {
        _type1Service = type1Service;
        _type2Service = type2Service;
    }

    public void Calculate(Measure measure)
    {
        var service = GetServiceForType(measure.measureType);

        service.Calculate(measure);
    }

    private IMeasureService GetServiceForType(MeasureType type)
    {
        switch (type)
        {
            case MeasureType.Type1:
                return _type1Service();
            case MeasureType.Type2:
                return _type2Service();
            default:
                throw new ApplicationException("Unexpected measure type!");
        }
    }
}

现在,使用原始的Measure类,只需要这个SM配置即可完成所有工作:

x.For<IMeasureService>().Use<MeasureServiceFactory>();

3)如果IMeasureService实现者​​中的逻辑不是很复杂,可以考虑将它放在一个类中,并根据measureType对象的Measure执行不同的操作(你已经有权访问)。

我知道,这似乎是后退一步,但在某些情况下,我更愿意这样做:当业务逻辑不是过于复杂而且不太可能改变时。