尽管使用了Unity.MVC3和HierarchicalLifetimeManager,但UnityOfWork实例创建了两次

时间:2013-01-22 17:23:00

标签: asp.net-mvc-3 unity-container

我在项目中使用Unity.MVC3。

我已经实现了通用工作单元 - UnitOfWork<TContext>,我希望每个请求都能创建它。所以利用Unity.MVC3我就这样做了:

unityContainer.RegisterType(typeof(IUnitOfWork<>), typeof(UnitOfWork<>), new HierarchicalLifetimeManager());

我在基础存储库中使用了提到的UOW。某些特定存储库使用基本存储库,某些服务使用这些特定存储库。

假设我们有UserRepository和UserService。

UserRepository构造函数或多或少看起来像这样:

    public UserRepository(IUnitOfWork<UserContext> unitOfWork)
        : base(unitOfWork)
    {           
    }

Inside UserService我正在使用UserRepository,我想拥有与UserRepository一样的UOW实例:

public UserService(IUserRepository userRepository, IUnitOfWork<UserContext> unitOfWork)
{
}

当我使用Unity.MVC3并使用HierarchicalLifetimeManager注册UOW时,我应该在UserRepository和UserService中获得相同的UOW实例,对吧?

问题在于,如果我第一次运行网站,则会创建两个不同的UOW实例,并且只调用这两个实例中的一个,调用Dispose方法。当页面加载并按下刷新按钮时,一切似乎都是正确的 - 只创建了一个实例。

似乎问题出现在注册的泛型类型中。

如果您想重现此问题,可以下载Unity.MVC3.Example代码,将IExampleContext设为通用并尝试运行。

您是否知道可能导致问题的原因以及如何解决此问题?提前谢谢。

2 个答案:

答案 0 :(得分:0)

实际上我认为PerResolveLifetimeManager就是您所需要的。

在依赖链中只创建一个UOW,但每次解析链时都会创建一个新的UOW。

HierarchicalLifetimeManager是相反的行为。

答案 1 :(得分:0)

这是我的替代解决方案:

我创建了PerRequestLifetimeManager:

public class PerRequestLifetimeManager<T> : LifetimeManager, IDisposable
{
    public override object GetValue()
    {
        return HttpContext.Current.Items[typeof(T).AssemblyQualifiedName];
    }
    public override void RemoveValue()
    {
        HttpContext.Current.Items.Remove(typeof(T).AssemblyQualifiedName);
    }
    public override void SetValue(object newValue)
    {
        HttpContext.Current.Items[typeof(T).AssemblyQualifiedName] = newValue;
    }
    public void Dispose()
    {
    }
}

Inside UserDomain我注册了IUnitOfWork类型:

RegisterType<IUnitOfWork<UsersContext>, UnitOfWork<UsersContext>>(new PerRequestLifetimeManager<IUnitOfWork<UsersContext>>());

我创建了PerRequestLifetimeHttpModule并在Web.config中注册了它:

public class PerRequestLifetimeHttpModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.EndRequest += (sender, e) => UnityDependencyResolver.DisposePerRequestLifetimeItems();
    }
    public void Dispose()
    {
    }
}

<system.webServer>
    <modules runAllManagedModulesForAllRequests="false">
        <add name="PerRequestLifetimeHttpModule" type="<namespace>.PerRequestLifetimeHttpModule, <assemblyName>" />
    </modules>
</system.webServer

最后一步 - 在我的自定义UnityDependencyResolver中创建了DisposePerRequestLifetimeItems静态函数,该函数在PerRequestLifetimeHttpModule中使用:

public static void DisposePerRequestLifetimeItems()
{
    foreach (var item in HttpContext.Current.Items.OfType<DictionaryEntry>().Where(item => item.Value is IDisposable))
    {
        ((IDisposable)item.Value).Dispose();
    }
}