我将添加必要的基础结构来将每个请求绑定到它自己的嵌套容器,所以在这种情况下,每个请求的容器给我们一个唯一的会话(每个请求的上下文),在我的代码我正在使用ObjectFactory的新实现:
public static class SmObjectFactory
{
private static readonly Lazy<Container> _containerBuilder =
new Lazy<Container>(defaultContainer, LazyThreadSafetyMode.ExecutionAndPublication);
public static IContainer Container
{
get { return _containerBuilder.Value; }
}
private static Container defaultContainer()
{
return new Container(ioc =>
{
ioc.For<IUnitOfWork>()
.HybridHttpOrThreadLocalScoped()
.Use<ApplicationDbContext>();
// config
});
}
}
所以,例如,如果我只是在ApplicationDbContext
的构造函数中设置一个断点,每次创建一个实例。例如,在我的情况下,我有这些控制器:
public partial class HomeController : Controller
{
private readonly IUnitOfWork _uow;
public HomeController(IUnitOfWork uow)
{
_uow = uow;
}
public virtual ActionResult Index()
{
return View();
}
}
public class TestController : Controller
{
private readonly IUnitOfWork _uow;
public TestController(IUnitOfWork uow)
{
_uow = uow;
}
public ActionResult GetData()
{
return Content("Data");
}
}
因此,Index操作返回的视图使用此代码从TestController
中提取内容:
@Html.Action("GetData", "Test")
在该示例中,每个请求创建了几个实例!
所以我用这种方式改变了SmObjectFactory
:
public class NewObjectFactory
{
public static IContainer Container { get; set; }
static NewObjectFactory()
{
Container = new Container();
Container.Configure(ioc =>
{
ioc.For<IUnitOfWork>()
.HybridHttpOrThreadLocalScoped()
.Use<ApplicationDbContext>();
// config
}
}
然后在Global.asax
我添加了这些代码行以使用嵌套容器:
public IContainer Container
{
get
{
return (IContainer)HttpContext.Current.Items["_Container"];
}
set
{
HttpContext.Current.Items["_Container"] = value;
}
}
public void Application_BeginRequest()
{
Container = NewObjectFactory.Container.GetNestedContainer();
}
public void Application_EndRequest()
{
Container.Dispose();
Container = null;
}
在Application_Start
内:
DependencyResolver.SetResolver(
new StructureMapDependencyResolver(() => Container ?? NewObjectFactory.Container));
在DependencyResolver中,我以这种方式实现了工厂功能:
public class StructureMapDependencyResolver : IDependencyResolver
{
private readonly Func<IContainer> _factory;
public StructureMapDependencyResolver(Func<IContainer> factory)
{
_factory = factory;
}
public object GetService(Type serviceType)
{
if (serviceType == null)
{
return null;
}
var factory = _factory();
return serviceType.IsAbstract || serviceType.IsInterface
? factory.TryGetInstance(serviceType)
: factory.GetInstance(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _factory().GetAllInstances(serviceType).Cast<object>();
}
}
最后,当我运行应用程序时,我收到此错误:
未注册默认实例,无法自动生成 确定类型 'Microsoft.Owin.Security.DataProtection.IDataProtectionProvider'
但是当我在Startup.cs
文件中评论此行时:
ConfigureAuth(app)
一切正常,这次ApplicationDbContext
创建一次,然后处理掉。这就是我想要的:现在只创建一个上下文实例,并在Web请求结束时正确处理它,这意味着嵌套容器重用上下文来满足两个控制器的依赖关系。 :)
有什么想法吗?