0

我正在尝试解决依赖于我正在调用的操作中的参数值的依赖关系。

我有这个 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");

是否可以根据选项的价值使用不同的价值提供者?

Ie, when option is "value1"then _valueProviderwill use the concrete type ValueProvider1and when option is "value2" then _valueProviderwill use the concrete type ValueProvider2.

4

2 回答 2

3

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

就是这样。如果你这样做,你仍然可以将选择逻辑提取到 anIValueProviderFactory中并将其注入到 中SwitchingValueProviderProxy,这使这个类保持简单和集中,并且仍然保持应用程序的其余部分对工厂一无所知。

于 2012-04-20T09:18:53.503 回答
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);
    }
}
于 2012-04-20T06:56:31.920 回答