【问题标题】:mvc5: Cannot access a disposed object. asp.net mvc5 using unitymvc5:无法访问已处置的对象。 asp.net mvc5 使用统一
【发布时间】:2019-04-07 14:37:58
【问题描述】:

我正在使用 vs 2013、mvc5 和 ef6 + unity.mvc5: 我的帐户控制器类有这个构造函数:

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

这是我的统一配置:

    container.RegisterType(typeof(AccountController),
            new InjectionConstructor(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>())));

当我尝试注册一个新用户时,我得到了这个异常:

Cannot access a disposed object.
Object name: 'UserManager`1'.

关于这行代码和注册动作:

var result = await UserManager.CreateAsync(user, model.Password);

当我删除统一并将依赖解析器设置为默认值时,它工作得很好。 我尝试了许多统一配置但没有用... 非常感谢阅读。

【问题讨论】:

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


    【解决方案1】:

    我找到了解决方案,将统一配置更改为:

    container.RegisterType<IUserStore<ApplicationUser>, 
                UserStore<ApplicationUser>>(new InjectionConstructor(new ApplicationDbContext()));
    

    谢谢大家。

    【讨论】:

      【解决方案2】:

      不要创建一个无参数的构造函数,(我不能拒绝它,因为我没有足够的声誉),这个答案完全避免了 IoC,而是尝试通过了解对象的整个依赖层次结构来构建对象,即 AccountController 需要知道它依赖于 UserStore,并且它需要知道 Userstore 依赖于 UserContext。这正是 DI 容器要避免的!

      由于缺少很多代码,因此很难为您提供准确的答案。

      我觉得奇怪的一件事是你有一个大写的UserManger,这通常意味着你将它用作一种类型,而不是引用本地私有变量。你能告诉我剩下的代码吗?

      另外,我会质疑您为什么不通过接口引用所有内容。到目前为止,这是设置适当 DI 的首选方式。

      我会尝试敲出一些测试代码来显示我会做什么,然后在这里发布,如果你能同时回答这些问题,那就太好了。

      迈克干杯

      【讨论】:

      • UserManager 是一个公共属性,不是我的帐户控制器,所以它是大写的。
      • 为什么要公开?其他任何东西都会通过控制器访问它吗?
      • 我正在使用 Visual Studio 2013,他们刚刚成功。顺便说一句,我没有改变它。
      • 好的,我明白你现在要做什么了。我已经为我的示例关闭了身份验证,因此我没有看到与您相同的情况。我真的不明白为什么该属性是公共的,如果您将其更改为私有,它仍然可以完美编译。
      • 是的,我只是忘了这样做。
      【解决方案3】:

      这就是我要做的。

      在你的控制器中

      public class HomeController : Controller
      {
          private IUserManager<ApplicationUser> userManager;
      
          public HomeController(IUserManager<ApplicationUser> userManager)
          {
              this.userManager = userManager;
          }
      
          public ActionResult Index()
          {
              var user = "user";
              var password = "password";
      
              var result = userManager.CreateAsync(user, password);
      
              return View();
          }
      }
      

      用户管理器接口

      public interface IUserManager<T> where T : ApplicationUser
      {
          int CreateAsync(string user, string password);
      }
      

      实际的 UserManager 类

      public class UserManager<T> : IUserManager<T> where T : ApplicationUser
      {
          private IUserStore<ApplicationUser> userStore;
      
          public UserManager(IUserStore<ApplicationUser> userStore)
          {
              this.userStore = userStore;
          }
      
          public int CreateAsync(string user, string password)
          {
              return 0;
          }
      }
      

      用户存储界面

      public interface IUserStore<T> where T : ApplicationUser
      {
      }
      

      实际用户存储

      public class UserStore<T> : IUserStore<T> where T : ApplicationUser
      {
      }
      

      统一配置

      container.RegisterType(typeof (IUserManager<>), typeof (UserManager<>));
      container.RegisterType(typeof (IUserStore<>), typeof (UserStore<>));
      

      希望这会有所帮助。

      显然有很多与您的应用程序不同的地方,即不执行异步调用方法,不从模型中读取密码等,但它应该让您了解如何解决您概述的问题.

      此解决方案将为您提供适当的构造函数依赖注入,这将允许您将所有配置集中在一个地方(即容器配置),它会在您的构造函数中为您提供接口,这将使您更容易在单元测试中模拟这些依赖项。

      迈克干杯

      【讨论】:

        猜你喜欢
        • 2018-11-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-23
        • 2011-03-25
        • 1970-01-01
        相关资源
        最近更新 更多