Meh*_*ili 45 asp.net singleton unity-container unit-of-work lifetime
几天前,我遇到了ASP.Net线程的这个问题.我希望每个Web请求都有一个单例对象.我的工作单位实际上需要这个.我想为每个Web请求实例化一个工作单元,以便身份映射在整个请求中有效.这样我就可以使用IoC透明地将我自己的IUnitOfWork注入到我的存储库类中,并且我可以使用相同的实例来查询然后更新我的实体.
由于我使用Unity,我错误地使用了PerThreadLifeTimeManager.我很快意识到ASP.Net线程模型不支持我想要实现的目标.基本上它使用theadpool并回收线程,这意味着每个线程我得到一个UnitOfWork!但是,我想要的是每个Web请求的一个工作单元.
一些谷歌搜索给了我这个伟大的帖子.这正是我想要的; 除了非常容易实现的统一部分.
这是我对PerCallContextLifeTimeManager实现统一的实现:
public class PerCallContextLifeTimeManager : LifetimeManager
{
private const string Key = "SingletonPerCallContext";
public override object GetValue()
{
return CallContext.GetData(Key);
}
public override void SetValue(object newValue)
{
CallContext.SetData(Key, newValue);
}
public override void RemoveValue()
{
}
}
Run Code Online (Sandbox Code Playgroud)
当然,我使用它来使用与此类似的代码注册我的工作单元:
unityContainer
.RegisterType<IUnitOfWork, MyDataContext>(
new PerCallContextLifeTimeManager(),
new InjectionConstructor());
Run Code Online (Sandbox Code Playgroud)
希望能节省一些时间.
小智 25
整洁的解决方案,但LifetimeManager的每个实例应使用唯一键而不是常量:
private string _key = string.Format("PerCallContextLifeTimeManager_{0}", Guid.NewGuid());
Run Code Online (Sandbox Code Playgroud)
否则,如果您在PerCallContextLifeTimeManager中注册了多个对象,则它们共享相同的密钥以访问CallContext,并且您将无法获得预期的对象.
还值得实现RemoveValue以确保清理对象:
public override void RemoveValue()
{
CallContext.FreeNamedDataSlot(_key);
}
Run Code Online (Sandbox Code Playgroud)
Ste*_*ins 21
虽然这可以调用这个PerCallContextLifeTimeManager,但我很确定这被认为是ASP.Net Per-request LifeTimeManager 并不 "安全".
如果ASP.Net进行线程交换,那么通过CallContext接受新线程的唯一事情就是当前的HttpContext - 你在CallContext中存储的任何东西都将消失.这意味着在重负载下,上面的代码可能会产生意想不到的结果 - 我想,追踪原因真的很痛苦!
唯一的"安全"方法是使用HttpContext.Current.Items,或者执行以下操作:
public class PerCallContextOrRequestLifeTimeManager : LifetimeManager
{
private string _key = string.Format("PerCallContextOrRequestLifeTimeManager_{0}", Guid.NewGuid());
public override object GetValue()
{
if(HttpContext.Current != null)
return GetFromHttpContext();
else
return GetFromCallContext();
}
public override void SetValue(object newValue)
{
if(HttpContext.Current != null)
return SetInHttpContext();
else
return SetInCallContext();
}
public override void RemoveValue()
{
}
}
Run Code Online (Sandbox Code Playgroud)
这显然意味着依赖于System.Web :-(
有关这方面的更多信息,请访问:
http://piers7.blogspot.com/2005/11/threadstatic-callcontext-and_02.html
归档时间: |
|
查看次数: |
15121 次 |
最近记录: |