一种方式使用同一个unitycontainer 不同的LifetimeManager:
I need one instance of an object to be created per HttpRequest in my ASP.NET MVC application. I think I can accomplish this with a custom LifetimeManager that stores created instances inside of HttpContext.Current.Items. If my class below works, how does one deal with objects created by Unity that need to have Dispose called? In my case, I have a service layer that takes a database context. At the end of my HttpRequest, Dispose should really be called on that object, yet I'm allowing Unity to handle the creation of it, and am storing it in HttpContext.Current.Items. Any thoughts on this issue?
Here's my HttpRequestLifetimeManager:
public class HttpRequestLifetimeManager : LifetimeManager
{
private readonly Guid key;
public HttpRequestLifetimeManager()
{
key = Guid.NewGuid();
}
public override object GetValue()
{
return HttpContext.Current.Items[key];
}
public override void SetValue(object newValue)
{
HttpContext.Current.Items[key] = newValue;
}
public override void RemoveValue()
{
HttpContext.Current.Items.Remove(key);
}
}
In Global.asax under Application_Start()
// Any request for a SystemEntityDatabase data context will provide one instance per HttpRequest
container.RegisterType<SystemEntityDatabase, SystemEntityDatabase>(new HttpRequestLifetimeManager());
另外一种指定注册类型为ContainerControlledLifetimeManager,而container使用session或者item的生命周期:
<unity>
<typeAliases>
<typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" />
</typeAliases>
<containers>
<container name="system">
<types>
<type name="a" type="Tjb.Facade.ILogger,Tjb.Facade" mapTo="Tjb.FacadeProvider.SystemLogger,Tjb.FacadeProvider" />
</types>
<!--<instances>
<add name="session" type="System.Boolean" value="false"/>
<add name="request" type="System.Boolean" value="false"/>
</instances>-->
</container>
<container name="session">
<types>
<type type="Tjb.Facade.ILogger,Tjb.Facade" mapTo="Tjb.FacadeProvider.SessionLogger,Tjb.FacadeProvider" >
<lifetime type="singleton" />
</type>
</types>
</container>
<container name="request">
<types>
<type type="Tjb.Facade.ILogger,Tjb.Facade" mapTo="Tjb.FacadeProvider.ItemLogger,Tjb.FacadeProvider" >
<lifetime type="singleton" />
</type>
</types>
</container>
</containers>
</unity>
引用某达人(ctavares)所说:
If you want to combine dispose semantics with per-request, an easier approach would be to use a per-request child container instead. Configure your main container in Application_Start. In BeginRequest, call container.CreateChildContainer();. Configure your per-request objects in the child container as ContainerControlledLifetime (you don't need the custom lifetime manager). Then, in EndRequest call Dispose on the child container. Then it'll take all the per-request stuff with it.
不知道这2种方式哪个更好?希望有高人指教。