依赖注入和工厂

and*_*ecu 6 c# dependency-injection factory-pattern

试图找出如何最好地处理以下场景:

假设一个RequestContext依赖于外部服务的类,例如:

public class RequestContext : IRequestContext
{
    private readonly ServiceFactory<IWeatherService> _weatherService;

    public RequestContext(ServiceFactory<IWeatherService> weatherService, UserLocation location, string query)
    {
       _weatherService = weatherService;
       ...
Run Code Online (Sandbox Code Playgroud)

我应该在最终实例化的类中需要什么样的依赖RequestContext?它可能是ServiceFactory<IWeatherService>,但这似乎不对,或者我可以创建一个IRequestContextFactory以下的线:

public class RequestContextFactory : IRequestContextFactory
{
    private readonly ServiceFactory<IWeatherService> _weatherService;

    public RequestContextFactory(ServiceFactory<IWeatherService> weatherService)
    {
        _weatherService = weatherService;
    }

    public RequestContext Create(UserLocation location, string query)
    {
        return new RequestContext(_weatherService, location, query);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后传递IRequestContextFactory构造函数注入.

这似乎是一种很好的方法,但这种方法的问题在于我认为它阻碍了可发现性(开发人员必须了解工厂并实施它,这并不是很明显).

我错过了更好/更可发现的方式吗?

Mar*_*ann 5

松散耦合的美妙之处在于我们可以不断隐藏之前的细节.

从IRequestContext的消费者的角度来看,RequestContext及其依赖关系的存在纯粹是一个实现细节.由于Liskov替换原则,消费者必须只处理IRequestContext:

public class MyClass
{
    private readonly IRequestContext reqCtx;

    public MyClass(IRequestContext reqCtx)
    {
        if (reqCtx == null)
        {
            throw new ArgumentNullException("reqCtx");
        }

        this.reqCtx = reqCtx;
    }

    // Implement using this.reqCtx...
}
Run Code Online (Sandbox Code Playgroud)

只有在应用程序的Composition Root中,您才需要最终将所有内容连接在一起.这是一个穷人的DI方法草图:

ServiceFactory<IWeatherService> weatherService =
    new ServiceFactory<IWeatherService>();
UserLocation location = new UserLocation;
string query = "foo";

IRequestContext reqCtx = new RequestContext(weatherService, location, query);

var mc = new MyClass(reqCtx);
Run Code Online (Sandbox Code Playgroud)