Tor*_*rfi 4 c# dependency-injection simple-injector asp.net-web-api
我正在使用带有ASP.NET Web API项目的Simple Injector,我想对一个接口使用不同的实现,具体取决于所使用的REST端点的版本.例如,如果使用端点的v1,IPaymentData则应使用调用的类进行实例化PaymentData,但如果使用v2 IPaymentData则应由调用的类实现PaymentDataNew.结果证明这是有问题的!
我不想使用类似Simple Injector文档的一部分的复合类,因为这意味着我的代码需要注意并考虑我正在使用的注入框架(坏).
我在最新版本(3.0)中注意到一种称为"基于上下文的注入"的功能.使用该container.RegisterConditional函数,每次解析类型时都应该可以运行委托.
container.RegisterConditional(typeof(IPaymentData),
c => ((HttpContext.Current.Items["version"] as string ?? "1") == "2")
? typeof(PaymentDataNew)
: typeof(PaymentData),
Lifestyle.Scoped,
c => true);
Run Code Online (Sandbox Code Playgroud)
但是,这似乎不起作用,因为即使生命周期是作用域,并且默认生活方式是WebApiRequestLifestyle根据版本返回实现的委托只调用第一个请求.后续请求跳过此(它们似乎使用缓存实现).
有什么我想念的吗?如何在每次请求进入时确保调用委托?
因为这意味着我的代码需要注意并考虑我正在使用的注入框架
不完全是.复合模式是众所周知且常用的模式,因此在代码中定义它不会使您的代码依赖于DI库.如果您不想在应用程序代码中定义组合,则可以始终在组合根中指定它.Composition Root已经非常依赖于DI库,因此任何特定于库的东西都应放在那里.
使用container.RegisterConditional函数,每次解析类型时都应该可以运行委托.
Simple Injector v3的RegisterConditional方法允许基于静态信息有条件地应用注册.这意味着所提供的谓词仅被称为有限的时间量(通常每个消耗组件一次).方法(IntelliSense/XML)文档说明:
谓词只会被评估有限次数; 谓词不适合根据运行时条件做出决策.
每次解决时都不会调用它.原因有两方面:
对象图的形状不应该依赖于运行时参数(例如version你的HttpContext).这样做会使对象图变得复杂,并且很难验证和诊断对象图的正确性.
我建议的解决方案是实现一个代理实现IPaymentData,允许在运行时进行切换.这不是 Simple Injector特定的实现; 你应该努力拥有简单,静态和可验证的对象图,而不管你使用的DI库.
这就是这样的代理可能的样子:
public sealed class HttpRequestVersionSelectorPaymentData : IPaymentData
{
private readonly PaymentData paymentOld;
private readonly PaymentDataNew paymentNew;
public VersionSelectorPaymentData(PaymentData old, PaymentDataNew paymentNew) { ... }
private bool New => HttpContext.Current.Items["version"] as string ?? "1") == "2";
private IPaymentData PaymentData => this.New ? paymentNew : paymentOld;
// IPaymentData method(s)
public Payment GetData(int id) => this.PaymentData.GetData(id);
}
Run Code Online (Sandbox Code Playgroud)
虽然绝对有可能在构建对象图期间做出运行时决策(通过注册委托),但我强烈建议不要这样做,原因如上所述.
| 归档时间: |
|
| 查看次数: |
794 次 |
| 最近记录: |