【问题标题】:Unity IoC Lifetime per HttpRequest for UserStoreUserStore 的每个 HttpRequest 的 Unity IoC 生命周期
【发布时间】:2014-04-10 02:30:39
【问题描述】:

我正在尝试清理新的 MVC5/Owin 安全实现中开箱即用的 AccountController.cs 的默认实现。我已将构造函数修改为如下所示:

private UserManager<ApplicationUser> UserManager;
public AccountController(UserManager<ApplicationUser> userManager)
{
    this.UserManager = userManager;
}

另外,我为 Unity 创建了一个生命周期管理器,如下所示:

 public class HttpContextLifetimeManager<T> : LifetimeManager, IDisposable
    {
        private HttpContextBase _context = null;
        public HttpContextLifetimeManager()
        {
            _context = new HttpContextWrapper(HttpContext.Current);
        }
        public HttpContextLifetimeManager(HttpContextBase context)
        {
            if (context == null)
                throw new ArgumentNullException("context");
            _context = context;
        }
        public void Dispose()
        {
            this.RemoveValue();
        }
        public override object GetValue()
        {
            return _context.Items[typeof(T)];
        }
        public override void RemoveValue()
        {
            _context.Items.Remove(typeof(T));
        }
        public override void SetValue(object newValue)
        {
            _context.Items[typeof(T)] = newValue;
        }
    }

我不确定如何在我的 UnityConfig.cs 中编写它,但这是我目前所拥有的:

container.RegisterType<UserManager<ApplicationUser>>(new HttpContextLifetimeManager(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new RecipeManagerContext()))));

我确实找到了另一个这样做的例子(使用 AutoFac):

container.Register(c => new UserManager<ApplicationUser>(new UserStore<ApplicationUser>( new RecipeManagerContext())))
                .As<UserManager<ApplicationUser>>().InstancePerHttpRequest();

如何使用 Unity IoC 生命周期管理翻译上述语句?

【问题讨论】:

    标签: c# dependency-injection unity-container asp.net-mvc-5 asp.net-identity


    【解决方案1】:

    您为特定生命周期注册UserManager 的方法是正确的。但是,我不明白为什么它甚至可以编译,因为您的 HttpContextLifetimeManager 需要 HttpContext 作为参数。

    另一个问题是你的实现是错误的。无参数构造函数采用 current http 上下文,但您更希望生命周期管理器使用实例 创建 的上下文,而不是类型 注册 的上下文强>上。如果使用无参数构造函数,这可能会导致 http 上下文不匹配问题。

    首先,将您的实现更改为

    public class HttpContextLifetimeManager : LifetimeManager
    {
     private readonly object key = new object();
    
     public override object GetValue()
     {
         if (HttpContext.Current != null && 
             HttpContext.Current.Items.Contains(key))
             return HttpContext.Current.Items[key];
         else
             return null;
     }
    
     public override void RemoveValue()
     {
         if (HttpContext.Current != null)
             HttpContext.Current.Items.Remove(key);
     }
    
     public override void SetValue(object newValue)
     {
         if (HttpContext.Current != null)
             HttpContext.Current.Items[key] = newValue;
     }
    }
    

    然后注册你的类型

    container.RegisterType<UserManager<ApplicationUser>>( new HttpContextLifetimeManager() );
    

    【讨论】:

    • 我认为如何实例化沿 DbContext 传递的 AccountController 内的对象?
    • 创建您自己的使用 unity 的构造函数工厂,stackoverflow.com/questions/14649545/… Unity 将负责解析完整的对象图。
    • 您链接的示例显示了 DI 在使用接口时如何工作,我已经理解了。我正在寻找如何指示 Unity 查看您看到的 ObjectType 以创建该对象的 X 实例。查看上面使用 Autofac 的行,注意它是在传递构造函数参数。
    • container.RegisterType&lt;UserManager&lt;ApplicationUser&gt;&gt;( new InjectionFactory( c =&gt; new UserManager&lt;ApplicationUser&gt;(new UserStore&lt;ApplicationUser&gt;( new RecipeManagerContext())), new HttpContextLifetimeManager() );
    • 你太棒了,谢谢。我不得不切换它,所以 HttpContextLifetimeManager() 是 RegisterType 的第一个参数,但它可以工作并且正是我想要的。检查了我的工作,一切看起来都很好。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2011-09-15
    • 2013-04-25
    • 1970-01-01
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多