根据structuremap中的参数解析具体类型

时间:2012-04-19 22:09:42

标签: c# dependency-injection structuremap

我正在尝试解析依赖于我正在调用的操作中的参数值的依赖项。

我有这个WCF服务

public class InformationService : IInformationService
{
    private readonly IValueProvider _valueProvider;

    public InformationService(IValueProvider valueProvider)
    {
        _valueProvider= valueProvider;
    }


    public CompanyReportResponse CompanyReport(string option)
    {
        _valueProvider.Execute(option);
    }
}

我还在容器中为我的ValueProvider注册了两个具体类型。

Registry.For<IValueProvider>().Add<ValueProvider1>().Named("No1");
Registry.For<IValueProvider>().Add<ValueProvider2>().Named("No2");

根据选项的价值,是否可以使用不同的Value Provider?

即,当选项为"value1"时,_valueProvider将使用具体类型ValueProvider1,当选项为"value2时,则_valueProvider将使用具体类型ValueProvider2

2 个答案:

答案 0 :(得分:2)

我看到至少2种不同的选择。

如果ValueProvider仅用于该方法,则可以考虑方法注入。由于在传递option参数时您已经知道将要使用哪一个,因此您可以提供IValueProvider的实现作为附加参数。

public CompanyReportResponse CompanyReport(string option, IValueProvider provider)
{
    _provider.Execute(option);
}

第二个选项是定义一个工厂来构建你的ValueProvider,并通过构造函数注入注入这个工厂。工厂将有一个方法来根据option参数实例化正确的ValueProvider。

public interface IValueProviderFactory
{
    IValueProvider CreateProvider(string option);
}

public class ValueProviderFactory : IValueProviderFactory
{
    public IValueProvider CreateProvider(string option)
    {
         // Insert custom instantiation logic here:
         // if option == "value1" return ValueProvider1 and so on
    }
}

public class InformationService : IInformationService
{
    private readonly IValueProviderFactory _valueProviderFactory;

    public InformationService(IValueProviderFactory valueProviderFactory)
    {
        _valueProviderFactory = valueProviderFactory;
    }

    public CompanyReportResponse CompanyReport(string option)
    {
        var valueProvider = _valueProviderFactory.CreateProvider(option);
        valueProvider.Execute(option);
    }
}

答案 1 :(得分:2)

+1 @ filpen的回答。我想添加第三个选项。您可以引入代理到正确实现的代理,而不是注入工厂或执行基于上下文的注入:

public SwitchingValueProviderProxy: IValueProvider
{
    private readonly ValueProvider1 provider1;
    private readonly ValueProvider2 provider2;

    public SwitchingValueProviderProxy(
        ValueProvider1 provider1,
        ValueProvider2 provider2)
    {
        this.provider1 = provider1;
        this.provider2 = provider2;
    }

    void IValueProvider.Execute(option option)
    {
        this.GetProvider(option).Execute(option);
    }

    private IValueProvider GetProvider(string option)
    {
        // custom instance logic here
        if (option.EndsWith("1"))
            return this.provider1;

        if (option.EndsWith("2"))
            return this.provider2;

        throw InvalidOperationException();
    }
}

这有一些明显的优势。首先,这完全隐藏了工厂和确定从客户端执行哪个提供程序的逻辑。客户端现在仅依赖于IValueProvider接口。接下来,配置现在变得非常干净:

Registry.For<IValueProvider>()
    .Add<SwitchingValueProviderProxy>();

就是这样。如果您仍然可以将选择逻辑提取到IValueProviderFactory并将其注入SwitchingValueProviderProxy,这将使该类简单且集中,并且仍然使应用程序的其余部分对工厂一无所知。 / p>