运行时的条件依赖项解析器(.net Core) [英] Conditional dependency resolver on run-time (.net Core)

查看:175
本文介绍了运行时的条件依赖项解析器(.net Core)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个类 PaymentGatewayFoo PaymentGatewayBoo 都实现了 IPaymentGateway的通用接口

I have two classes PaymentGatewayFoo, PaymentGatewayBoo that both implements a common interface of IPaymentGateway:

interface IPaymentGateway { }

class PaymentGatewayFoo : IPaymentGateway { }
class PaymentGatewayBoo : IPaymentGateway { }

客户端请求具有一个标识符,该标识符可以响应以确定使用哪种实现:

The client side request has an identifier who's response to determine which implementation to use:

public class OrderService
{
    private readonly IPaymentGateway _service;

    public void DoOrder(bool isFoo)
    {
        if (isFoo)
            //this._service should be resolved with PaymentGatewayFoo
        else
            //this._service should be resolved with PaymentGatewayBoo

        this._service.Pay();
    }
}

如何根据客户的解决方案来解决正确的实现请求运行时?

How do I resolve the proper implementation based on the client's request on run-time?

问题不是重复的,它是相似的,但是它是关于两个单独的控制器的(即使答案表明该代码甚至不需要条件依赖注入),在我的情况下,运行时需要条件依赖时间基于客户端属性值。

This question is not duplicate, its similar but its about two separate controllers (Even the answers suggested that the code didn't even needed the conditional dependency injection), in my case the conditional dependency is needed on run-time based on a client property value.

推荐答案

这里有几种选择,但是对我来说,这两种选择最明显正在使用工厂或适配器模式。

There are several options here, but the two that to me are the most obvious are using a factory or the adapter pattern.

public class OrderService
{
    private readonly IPaymentGatewayFactory _factory;

    public void DoOrder(bool isFoo)
    {
        var service = _factory.Create(isFoo);
        this._service.Pay();
    }
}

工厂可以在哪里:

public class PaymentGatewayFactory : IPaymentGatewayFactory 
{
    public PaymentGatewayFactory(PaymentGatewayFoo foo, PaymentGatewayBoo boo) {...}

    public IPaymentGateway Create(bool isFoo) =>
        isFoo ? this.foo : this.boo;
}

使用工厂的缺点是消费者需要了解两种抽象:工厂和工厂。 IPaymentGateway。

Downside of using a factory is that the consumer needs to be aware of two abstractions: the factory and the IPaymentGateway.

public class OrderService
{
    private readonly IPayment _payment;

    public void DoOrder(bool isFoo)
    {
        _payment.Pay(isFoo);
    }
}

其中的适配器可以是:

public class PaymentAdapter : IPayment
{
    public PaymentAdapter(PaymentGatewayFoo foo, PaymentGatewayBoo boo) {...}

    public void Pay(bool isFoo)
    {
        var service = isFoo ? this.foo : this.boo;

        service.Pay();
    }
}

这样做的好处是客户只需要意识到一个抽象。缺点是您需要第二个抽象。

Advantage of this is that the client only needs to be aware of a single abstraction. Downside is that you need a second abstraction.

您注意到,在我的工厂和适配器中,实现将直接注入。甚至不是通过抽象,而是通过具体类型。这可能看起来很奇怪,但是只要适配器和工厂是应用程序入口点的一部分(也称为构成根)。

As you noticed, in my factory and adapter, the implementations are injected directly. Not even by their abstractions, but by their concrete types. This might seem strange, but doing so is completely fine as long as the adapter and factory are part of the application's entry point (a.k.a. the Composition Root).

但其他更动态的选项可以使用,例如:

But other, more dynamic options can be used, such as:


  • 注入 Func< PaymentType,IPaymentGateway>

  • 注入 Dictionary< PaymentType,IPaymentGateway>

  • 注入IPaymentGateway实现的集合。

  • 注入容器本身

  • 使用动态过滤(如Armand建议的那样),但请注意,这会导致您添加接口的 Identifier 属性,该属性仅出于技术原因而存在。没有任何消费者(适配器或工厂除外)对此标识符感兴趣。因此,它不属于该界面。更好的解决方案是解决合成根中的此问题,例如可以通过使用属性标记实现

  • Injecting a Func<PaymentType, IPaymentGateway> delegate to resolve the types.
  • Injecting a Dictionary<PaymentType, IPaymentGateway>.
  • Injecting a collection of IPaymentGateway implementations.
  • Injecting the container itself
  • Using dynamic filtering, as Armand suggests, but do note that is causes you to add the Identifier property to the interface, where it only exists for technical reasons. No consumer (other than the adapter or the factory) is interested in this identifier. It, therefore, doesn't belong to the interface. A better solution is to solve this problem in the Composition Root, possibly by marking the implementations with an attribute, for instance.

这篇关于运行时的条件依赖项解析器(.net Core)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆