问题 自定义成员资格提供程序的依赖注入


我有一个ASP.NET MVC Web应用程序,实现自定义成员资格提供程序。自定义成员资格提供程序需要 UserRepository 到它的构造函数,它提供了成员资格提供者和NHibernate之间的接口。该 UserRepository 由Ninject IoC容器提供。

但是,显然,当.NET实例化提供程序时,这不起作用:无参数构造函数没有UserRepository而且无法创建一个(UserRepository需要将NHibernate会话传递给它的构造函数),这意味着提供者无法访问其数据存储。如何解决对象依赖?

值得注意的是,这是一个已经使用Ninject进行改造的现有应用程序。以前我使用无参数构造函数,它们能够与参数化构造函数一起创建所需的依赖项,以帮助进行单元测试。

有什么想法,还是我把自己建在角落里?


11167
2018-05-02 12:19


起源



答案:


您可能希望保留无参数构造函数,即使用Ninject初始化所需的存储库。你可能想要使用 公共服务定位器,因此您不需要在自定义提供程序中既没有引用Ninject也没有它的容器。似乎Ninject没有官方的CSL适配器实现,但写一个不应该很难(检查其他实现,如Windsor的),我确信在某处有一个非官方的实现。


5
2018-05-02 14:18



Ninject于2010年1月推出了官方CSL适配器。 - Ian Davis
它仍然缺少CSL主页(它包​​含在NInject版本中) - SztupY
“构造函数,使用Ninject初始化所需的存储库” - 注意,如果您的存储库(或其依赖项)处于Request或Transient范围内并且任何类型的一次性数据上下文发挥作用,您将最终访问已处置的数据上下文除了第一个请求之外的所有请求(因为您不控制Provider的生命周期,ASP.NET将在请求之间重用它)。当我遇到这个问题时,每次需要调用一个实例时,我最终都会从定位器获取一个存储库实例。 - Jakub Januszkiewicz
来自Fabio70a的评论:这是解决方案: stackoverflow.com/questions/1551503/... - StuartLC


答案:


您可能希望保留无参数构造函数,即使用Ninject初始化所需的存储库。你可能想要使用 公共服务定位器,因此您不需要在自定义提供程序中既没有引用Ninject也没有它的容器。似乎Ninject没有官方的CSL适配器实现,但写一个不应该很难(检查其他实现,如Windsor的),我确信在某处有一个非官方的实现。


5
2018-05-02 14:18



Ninject于2010年1月推出了官方CSL适配器。 - Ian Davis
它仍然缺少CSL主页(它包​​含在NInject版本中) - SztupY
“构造函数,使用Ninject初始化所需的存储库” - 注意,如果您的存储库(或其依赖项)处于Request或Transient范围内并且任何类型的一次性数据上下文发挥作用,您将最终访问已处置的数据上下文除了第一个请求之外的所有请求(因为您不控制Provider的生命周期,ASP.NET将在请求之间重用它)。当我遇到这个问题时,每次需要调用一个实例时,我最终都会从定位器获取一个存储库实例。 - Jakub Januszkiewicz
来自Fabio70a的评论:这是解决方案: stackoverflow.com/questions/1551503/... - StuartLC


来自Michael B.的正确答案: 依赖注入和ASP.Net成员提供商

您可以通过以下方式获取存储库(或服务)注入:

public IRepository Repository { get { return DependencyResolver.Current.GetService(IRepository ); } }

5
2017-12-12 12:05





由于在Ninject可以实例化它们之前创建了成员资格集合和MemberShip.Provider实例,因此您需要对该对象执行创建后激活。如果使用[Inject]在提供程序类中为属性标记依赖项,则可以调用kernel.Inject(MemberShip.Provider) - 这将为属性分配所有依赖项。


4
2017-11-08 13:46



听起来不错;我用CSL解决了它,但是可能值得重新访问以消除额外的依赖性。 - alastairs
+1我喜欢这种方法。 - Pandincus
你会在哪里调用kernel.Inject ...? - Matt


我遇到了同样的问题,我通过使用身份验证票据将所需数据传递给身份对象来解决它。

然后,不需要将对象注入成员资格提供者。

在我的身份验证代码中

    [NonAction]
    private void SetAuthTicket(Member member, bool isPersistent)
    {
        HttpCookie cookie = Request.Cookies.Get(FormsAuthentication.FormsCookieName);

        FormsAuthentication.SetAuthCookie(member.Email, isPersistent);

        string userData = "|" + member.ID + "|" + member.Firstname + "|" + member.Lastname + member.Culture;

        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, member.Email, DateTime.UtcNow, DateTime.UtcNow.AddDays(7), isPersistent, userData);

        string encryptedTicket = FormsAuthentication.Encrypt(ticket);
        cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
        Response.Cookies.Add(cookie);
    }

并在Global.asax

    void Application_OnPostAuthenticateRequest(object sender, EventArgs e)
    {
        IPrincipal user = HttpContext.Current.User;
        if (user.Identity.IsAuthenticated && user.Identity.AuthenticationType == "Forms")
        {
            FormsIdentity identity = user.Identity as FormsIdentity;

            MyIdentity ai = new MyIdentity(identity.Ticket);            
            MyPrincipal p = new MyPrincipal(ai);

            HttpContext.Current.User = p;
            System.Threading.Thread.CurrentPrincipal = p;

            if (!String.IsNullOrEmpty(ai.Culture))
            {
                CultureInfo ci = new CultureInfo(ai.Culture);
                System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
                System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
            }
        }
    }

在Identity类中,我有MemberName,Firstname和Lastname属性,它们返回部分票证字符串。


-1
2018-05-02 12:24



请问你能详细一点吗?例如,CreateUser()如何覆盖场景中的函数?你是说在我的场景中我必须在身份验证票据中传递存储库对象吗? - alastairs
而不是传递存储库传递用户ID - Daniil Harik
什么??我同意@alastairs,如何在没有存储库的情况下创建用户和其他东西? - mare