【问题标题】:MVC 3 ninject custom membership context disposed errorMVC 3 ninject 自定义成员资格上下文处理错误
【发布时间】:2011-11-10 10:17:30
【问题描述】:

我有一个自定义成员资格,它使用我的 CustomerService 首先使用 EF 代码与数据库进行通信 (4.1) 我使用 ninject 将 CustomerService 注入到我的自定义成员资格类中。 但是当我尝试验证时,我得到一个上下文处理错误。 这是因为在我的上下文中,存储库和服务是 InRequestScope()。 因为我在自定义成员的属性上使用 [inject] 注入 CustomerService,而在 ninject 中使用 _kernel.Inject(Membership.Provider),它只在启动时注入。

我阅读了很多关于这个问题的帖子,但找不到解决这个问题的答案。

有没有人可以解决这个问题?

【问题讨论】:

    标签: asp.net-mvc ninject membership


    【解决方案1】:

    对于刚开始使用 DI 和 IoC 容器的人来说,这是一个常见的错误。您必须保持范围的一致性。当依赖于它们的服务绑定到单例范围(或者更糟糕的是,某些范围根本不由容器管理)时,您不能将依赖项绑定到请求范围。这完全是错误的。

    这里有两个基本选项:

    1. CustomerService 与成员资格提供程序本身绑定为InSingletonScope。显然,这具有长期 EF 服务的所有常见缺点。

    2. 不要让您的成员资格提供程序依赖于 CustomerService 实例。相反,建立对 CustomerServiceFactory 的依赖关系,它可以创建 CustomerService 实例,并将对成员资格提供程序的每次调用都视为瞬态。

    对于#2,创建和绑定工厂的过程非常简单:

    public interface ICustomerServiceFactory
    {
        ICustomerService GetService();
    }
    
    public class NinjectCustomerServiceFactory : ICustomerServiceFactory
    {
        private readonly IKernel kernel;
    
        public NinjectCustomerServiceFactory(IKernel kernel)
        {
            if (kernel == null)
                throw new ArgumentNullException("kernel");
            this.kernel = kernel;
        }
    
        public ICustomerService GetService()
        {
            return kernel.Get<ICustomerService>();
        }
    }
    

    然后在你的模块中:

    Bind<ICustomerService>()
        .To<EFCustomerService>();
        .InRequestScope();
    Bind<ICustomerServiceFactory>()
        .To<NinjectCustomerServiceFactory>()
        .InSingletonScope();
    

    注意这里的范围。服务本身仍然是请求范围的,但工厂是单例的,与提供者的范围相同。这是可行的,因为工厂直接进入内核,内核也是单例(或多或少)。

    您最终会得到如下所示的会员代码:

    public class MyMembershipProvider : MembershipProvider
    {
        public override MembershipUserCollection GetAllUsers()
        {
            var service = serviceFactory.GetService();
            var serviceUsers = service.GetAllUsers();
            return serviceUsers.Select(u => CreateMembershipUser(u));
        }
    
        // Other methods...
    
        [Inject]
        public ICustomerServiceFactory ServiceFactory { get; set; }
    }
    

    这实际上工作得很好,因为服务本身仍然是请求范围的,但是工厂(以及成员资格提供者)在每个请求期间只会获得不同的实例。不仅如此,无论在单个请求期间调用了多少个成员资格方法,成员资格提供者都可以保证(通过工厂)获得 same 实例。因此,尽管必须集成到遗留代码中,但您几乎可以获得 DI 的所有好处。

    【讨论】:

    • 感觉很愚蠢,在浏览 ninject 未在我的会员资格提供程序中注入属性的问题时,我什至没有阅读问题,我实现了其他问题的解决方案......当然,它仍然没有注入属性。而且我不能在会员提供者中使用构造函数指令...
    猜你喜欢
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多