ASP.NET 5(RC1)为我们提供了一个全新的配置模型,我们在其中添加/替换ServiceDescriptor对象集合的配置.替换默认实现很简单,例如:
services.Add(ServiceDescriptor.Instance<IHttpContextAccessor>(
new MyHttpContextAccessor()));
但是,我很难找到一种方法来扩展现有注册的额外行为(通过装饰).换句话说,我想用内部使用内置版本的自定义版本替换内置版本.以这种方式扩展框架行为当然很常见.例如:
// How to get the instance here???
IHttpContextAccessor original =
services.Last(service => service.ServiceType == typeof(IHttpContextAccessor));
services.Add(ServiceDescriptor.Instance<IHttpContextAccessor>(
new HttpContextAccessorDecorator(original)));
请注意,使用IHttpContextAccessor只是一个示例,但确实有效地显示了问题. services集合包含ServiceDescriptor对象,对于IHttpContextAccessor,ImplementationInstance和ImpementationFactory属性为空,因此无法获取该原始实例.我们不能将一个IServiceProvider注入装饰器来延迟注册,因为一旦我们在装饰器中请求IHttpContextAccessor,我们就会得到相同的装饰器,这将导致堆栈溢出异常.
有趣的是,使用MVC 5和Web API,这实际上非常简单.
如何在ASP.NET 5中实现相同的功能?
最佳答案 你可以通过建立一个“中间”服务提供商以一种黑客的方式实现这一目标.然后,您可以检索原始实现的实例,并在创建自己的实例时使用它:
var innerSp = services.BuildServiceProvider();
var original = innerSp.GetService<IHttpContextAccessor>();
services.AddInstance<IHttpContextAccessor>(new HttpContextAccessorDecorator(original));
这需要Microsoft.Extensions.DependencyInjection包(而不是Abstractions),因为它使用内部ServiceProvider实现.
当然,这是一个糟糕的解决方案,我同意我们需要更好的东西.