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
属性为空,因此无法获取原始实例。我们不能在装饰器中注入(inject) IServiceProvider
来延迟注册,因为一旦我们在装饰器中请求 IHttpContextAccessor
,我们将得到相同的装饰器,这将导致计算器异常。
有趣的是,使用 MVC 5 和 Web API,这实际上真的很简单。
如何使用 ASP.NET 5 实现同样的目标?
最佳答案
您可以通过构建“中间”服务提供商以一种hacky的方式实现这一点。然后您可以检索原始实现的实例并在创建您自己的实例时使用它:
var innerSp = services.BuildServiceProvider();
var original = innerSp.GetService<IHttpContextAccessor>();
services.AddInstance<IHttpContextAccessor>(new HttpContextAccessorDecorator(original));
这需要 Microsoft.Extensions.DependencyInjection
包(不是 Abstractions
包),因为它使用内部 ServiceProvider
实现。
当然,这是一个糟糕的解决方案,我同意我们需要更好的解决方案。
关于c# - 如何包装和替换 ASP.NET 5 配置中的默认组件之一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34206466/