MVC 3 ninject自定义成员资格上下文错误

1 membership asp.net-mvc ninject

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

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

有人有解决方案吗?

Aar*_*ght 9

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

这里有两个基本选项:

  1. CustomerServiceas 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>();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的模块中:

Bind<ICustomerService>()
    .To<EFCustomerService>();
    .InRequestScope();
Bind<ICustomerServiceFactory>()
    .To<NinjectCustomerServiceFactory>()
    .InSingletonScope();
Run Code Online (Sandbox Code Playgroud)

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

您最终会看到会员代码:

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; }
}
Run Code Online (Sandbox Code Playgroud)

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