在传统的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);
问题是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; }
}
}
此代码似乎有效。 IDisposable
个对象在请求的末尾处理。 InstancePerRequest
配置正常。
这个实现有没有问题(表演,记忆......)?
答案 0 :(得分:0)
如果它可以帮助其他人,请按照以下方式将其实现为请求处理程序。
这是我的Startup.cs:
Template.series72.onRendered(function(){
$('.download').attr({
download: '',
target: '_blank',
href : '../pdfs/sizing-diagram-series-72.pdf'
});
});
我将在下面显示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());
}
}
。
这是我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;
}
在我的用例中,我有一个第三方库,它使用IoC通过存储库模式解析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);
}
}
实现。
这个库在其他使用其他DI容器的环境中使用,当使用默认的DBContext
root设置时,我会看到旧数据的EF缓存问题或者写入失败,因为新的上下文将是在对象添加和提交之间创建。
非常感谢OP帮助我们解决这个问题。