Pas*_*mey 6 asp.net webforms lifetime autofac
在传统的Asp.NET webforms应用程序中,我尝试注入一些IOC.
我不会详细介绍,但对于这一点,我认为ServiceLocator是一个很好的工具.我知道服务定位器是反模式的; o)
根据文档https://github.com/autofac/Autofac/wiki/Common-Service-Locator,ServiceLocator配置如下所示:
var container = builder.Build();
var csl = new AutofacServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => csl);
Run Code Online (Sandbox Code Playgroud)
问题是LoacatorProvider是使用根容器设置的.因此,终身管理不活跃.
我正在考虑解决这个问题的方法
因为ServiceLocator.SetLocatorProvider将一个委托作为参数,并且因为在每次调用时调用此委托,ServiceLocator.Current为什么不为每个请求提供一个AutofacServiceLocator实例.
public class Global : HttpApplication, IContainerProviderAccessor
{
// Provider that holds the application container.
static IContainerProvider _containerProvider;
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
_containerProvider = new ContainerProvider(AutoFacBootstrapper.CreateContainer());
ServiceLocator.SetLocatorProvider(() =>
{
AutofacServiceLocator asl = HttpContext.Current.Items["AutofacServiceLocator"] as AutofacServiceLocator;
if (asl == null)
{
var cpa = (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
var cp = cpa.ContainerProvider.RequestLifetime;
asl = new AutofacServiceLocator(cp);
HttpContext.Current.Items["AutofacServiceLocator"] = asl;
}
return asl;
});
}
public IContainerProvider ContainerProvider
{
get { return _containerProvider; }
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码似乎有效.IDisposable对象在请求结束时处理.InstancePerRequest配置还可以.
这个实现有什么问题(表演,记忆......)吗?
如果它对其他人有帮助,以下是我将其作为请求处理程序实现的方法。
这是我的 Startup.cs:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
// ...
IContainer container = ConfigureAutofac(config);
// This should be the first middleware added to the IAppBuilder.
app.UseAutofacMiddleware(container);
// Make sure the Autofac lifetime scope is passed to Web API.
app.UseAutofacWebApi(config);
app.UseWebApi(config);
config.MessageHandlers.Add(new ServiceLocatorHandler());
}
}
Run Code Online (Sandbox Code Playgroud)
下面我就展示一下ServiceLocatorHandler.cs。
ConfigureAutofac为了完整性,这是我的函数:
private IContainer ConfigureAutofac(HttpConfiguration config)
{
var builder = new ContainerBuilder();
var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>();
builder.RegisterAssemblyModules(assemblies.ToArray());
// Register Web API classes
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterWebApiFilterProvider(config);
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
// Register the modules
// ...
// Create the container
var container = builder.Build();
// Hook up the Web API dependency resolver
var resolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = resolver;
// ...
ServiceLocator.SetLocatorProvider(() => new AutofacServiceLocator(container));
return container;
}
Run Code Online (Sandbox Code Playgroud)
最后,这是处理程序:
public class ServiceLocatorHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var properties = request.Properties;
var scope = properties["MS_DependencyScope"];
AutofacWebApiDependencyScope dependency_scope = scope as AutofacWebApiDependencyScope;
if (dependency_scope != null && dependency_scope.LifetimeScope != null)
{
AutofacWebApiDependencyResolver resolver = new AutofacWebApiDependencyResolver(dependency_scope.LifetimeScope);
AutofacServiceLocator asl = new AutofacServiceLocator(resolver.Container);
ServiceLocator.SetLocatorProvider(() => asl);
}
return base.SendAsync(request, cancellationToken);
}
}
Run Code Online (Sandbox Code Playgroud)
在我的用例中,我有一个第三方库,它使用 IoCDBContext通过存储库模式来解析实现。
该库在使用其他 DI 容器的其他环境中使用,当将其与默认AutofacServiceLocator根设置一起使用时,我会看到旧数据的 EF 缓存问题,或者写入失败,因为在对象添加和提交之间会创建新上下文。
非常感谢OP帮助我们解决这个问题。
| 归档时间: |
|
| 查看次数: |
990 次 |
| 最近记录: |