我知道这个问题可能看起来像重复的一样,但请让我解释一下。

因此,我创建了几个使用可插拔架构的组件,基本上,我可以自由地添加新的实现,它们将自动为我注入和处理。在某些情况下,这确实很方便。

我将讨论最简单的一种,即验证组件。

使用这样的设计的原因之一是,我喜欢明确公开自己的角色,如Udi Dahan所述

基本上我有这样的代码:

public interface IValidatorRuner
{
    void Run<TTarget>(TTarget target);
}

public class ValidatorRunenr : IValidatorRuner
{
    private readonly IServiceLocator _serviceLocator;

    public ValidatorRunenr(IServiceLocator serviceLocator)
    {
        _serviceLocator = serviceLocator;
    }

    public void Run<TTarget>(TTarget target)
    {
        // this is the dynamic/pluggable phase
        // is this an antipattern???
        var foundValdiators = _serviceLocator.GetAllInstances<IValidator<TTarget>>();

        foreach (var valdiator in foundValdiators)
        {
            valdiator.IsSatisfiedBy(target);
        }
    }
}


此代码使我可以明确地公开我的验证规则,如下所示:

//this will allow me to create validators in this way
//and they will be automatically injected and resolved for me
//(easy, to read, easy to write, easy to test, pff I could even smoke this validator easily)
public class OneValdiationRuleExplicitlyExposedAndEasyToTest : IValidator<Person>
{
    public bool IsSatisfiedBy(Person target)
    {
        return target.Age > 18;
    }
}

public class Person
{
    public int Age { get; set; }
}

public interface IValidator<TTarget>
{
    bool IsSatisfiedBy(TTarget target);
}


我将使用如下代码:

//usage
public class SomeCommandHandler
{
    private readonly IValidatorRuner _validatorRuner;

    public SomeCommandHandler(IValidatorRuner validatorRuner)
    {
        _validatorRuner = validatorRuner;
    }

    public void SomeMethod()
    {
        _validatorRuner.Run(new Person{Age = 16});
    }
}


验证只是一个示例,我还使用它来触发域事件并以相同的可插入方式运行管道和过滤器

以这种方式使用服务定位器是否是反模式?

我知道我可能隐藏了一些依赖关系,但事实是,这些依赖关系是在应用程序初始化时动态注入并发现的(Composition root

您的想法将不胜感激

最佳答案

我认为,代码示例的主要问题是服务定位器本身已注入ValidatorRunner的实现中。对我来说,这是一种反模式,但也许不是您要问的那种。

我可能给出的任何答案都归结为您的服务定位器实现的功能。但是可以肯定的是,不应将其传递到类的构造函数中。相反,当您要求服务定位器实现“ IValidatorRuner”的实现时,服务定位器本身应将这些内容传递给

例如,您可以注入一个工厂,该工厂知道如何为给定类型加载动态验证器实例。

09-04 06:42