如何包装和替换ASP.NET 5配置中的一个默认组件

ASP.NET 5(RC1)为我们提供了一个全新的配置模型,我们将配置添加/替换为ServiceDescriptor对象的集合。 替换默认实现很简单,例如:

 services.Add(ServiceDescriptor.Instance( new MyHttpContextAccessor())); 

但是,我很难找到一种方法来扩展现有注册的额外行为(通过装饰)。 换句话说,我想用内部使用内置版本的自定义版本替换内置版本。 以这种方式扩展框架行为当然很常见。 例如:

 // How to get the instance here??? IHttpContextAccessor original = services.Last(service => service.ServiceType == typeof(IHttpContextAccessor)); services.Add(ServiceDescriptor.Instance( new HttpContextAccessorDecorator(original))); 

请注意,使用IHttpContextAccessor只是一个示例,但确实有效地显示了问题。 services集合包含ServiceDescriptor对象,对于IHttpContextAccessorImplementationInstanceIHttpContextAccessor属性为空,从而无法获取该原始实例。 我们不能将一个IServiceProvider注入装饰器来延迟注册,因为一旦我们在装饰器中请求一个IHttpContextAccessor ,我们就会得到相同的装饰器,这将导致一个stackoverflowexception。

有趣的是,使用MVC 5和Web API,这实际上非常简单。

如何在ASP.NET 5中实现相同的function?

可以通过建立一个“中间”服务提供商以一种黑客的方式实现这一目标。 然后,您可以检索原始实现的实例,并在创建自己的实例时使用它:

 var innerSp = services.BuildServiceProvider(); var original = innerSp.GetService(); services.AddInstance(new HttpContextAccessorDecorator(original)); 

这需要Microsoft.Extensions.DependencyInjection包(而不是Abstractions ),因为它使用内部ServiceProvider实现。

当然,这是一个糟糕的解决方案,我同意我们需要更好的东西。