2

我在我的项目中使用 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)
    {           
    }

在 UserService 内部,我使用的是 UserRepository,我希望拥有与 UserRepository 使用的相同的 UOW 实例:

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

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

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

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

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

你知道什么会导致问题以及如何解决这个问题吗?先感谢您。

4

2 回答 2

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()
    {
    }
}

在 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 中,我创建了在 PerRequestLifetimeHttpModule 中使用的 DisposePerRequestLifetimeItems 静态函数:

public static void DisposePerRequestLifetimeItems()
{
    foreach (var item in HttpContext.Current.Items.OfType<DictionaryEntry>().Where(item => item.Value is IDisposable))
    {
        ((IDisposable)item.Value).Dispose();
    }
}
于 2013-03-13T18:42:43.913 回答
0

其实我认为 PerResolveLifetimeManager 是你需要的。

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

HierarchicalLifetimeManager 是相反的行为。

于 2013-03-06T10:34:51.303 回答