我遇到了同样的问题——使用 ASP.NET——ResourceProviderFactory
不幸的是,答案是你必须使用 service location。
任何可以注入任何东西或更改内置 ASP.NET 行为的管道都没有“挂钩”。因此,如果您需要将某些内容放入属性中,则必须在构造函数中进行设置。
public class SqlResourceProviderFactory : ResourceProviderFactory
{
public IServiceManager ServiceManager { get; set; }
public SqlResourceProviderFactory()
{
this.ServiceManager =
DependencyResolver.Current.GetService<IServiceManager>();
}
}
是的,真的很丑
这里需要考虑的非常重要的一点,尤其是关于 Autofac,是您IServiceManager
注册的生命周期范围。
被ResourceProviderFactory
创建一次并被缓存。与来自 Create* 方法的全局/本地资源提供程序相同。我们在这方面玩得很开心,因为这意味着HttpContext
在创建工厂时不一定有一个InstancePerHttpRequest
.
- 您的或生成的资源提供者使用的任何东西
ResourceProviderFactory
- 一直到堆栈 - 都应该注册SingleInstance
或InstancePerDependency
。
- 如果可能,直接引用应用程序容器,而不是使用
DependencyResolver.Current
(对于 Autofac,它需要一个 active )。HttpContext
这意味着您需要在其他地方存储对它的引用(全局静态变量?)并使用它。
这是更完整的解决方案可能涉及的内容:
// Create some "holder" for the app container.
public static class ApplicationContainerProvider
{
public static ILifetimeScope Container { get; set; }
}
// In Global.asax, build your container and set it in both
// the DependencyResolver AND in the holder class.
var builder = new ContainerBuilder();
builder.RegisterType<Something>().As<ISomething>();
var container = builder.Build();
var resolver = new AutofacDependencyResolver(container);
DependencyResolver.SetResolver(resolver);
ApplicationContainerProvider.Container = container;
// In your service location, reference the container instead of
// DependencyResolver.
public class SqlResourceProviderFactory : ResourceProviderFactory
{
public IServiceManager ServiceManager { get; set; }
public SqlResourceProviderFactory()
{
this.ServiceManager =
ApplicationContainerProvider.Container.Resolve<IServiceManager>();
}
}
请注意,由于您是从根容器中解决该问题的,因此它将在应用程序的整个生命周期内一直存在。即使您将其注册为InstancePerDependency
,由于 .NET 的内部缓存,它也只会创建一次。
如果您不喜欢这样创建自己的静态持有者类,您可以使用CommonServiceLocator
和Autofac.Extras.CommonServiceLocator
包将其抽象出来。