仅当属性不为null时,条件依赖注入绑定

时间:2014-04-01 17:41:53

标签: c# nhibernate dependency-injection ninject conditional-binding

这是一个桌面应用程序,在访问基础数据源时必须模拟当前用户。

如果父对象的属性不为null,我怎么能告诉Ninject不绑定依赖项?

  1. 应用程序在启动时强制进行用户身份验证
  2. 经过身份验证后,对当前用户凭据的引用将保留在IMembershipService
  3. 访问基础数据源必须对用户进行身份验证,以便纪念字符串声明要模拟的凭据
  4. 我实际上正在使用NHibernate,我需要根据身份验证时提供的用户凭据动态创建连接字符串。

    所以我想实现:

    public class DataModule : NinjectModule {
        public override void Load() {
            Bind<ISessionFactory>().ToProvider<SessionFactoryProvider>()
                .When( // IMembershipService.CurrentUser != null );
        } 
    }
    

    由于SessionProviderFactory取决于IMembershipService.CurrentUser

    我知道这可能不是本世纪的设计,除此之外我现在需要它以这种方式工作,以便我可以提供我的潜在可交付产品。之后我很乐意重构。

    SessionFactoryProvider

    public class SessionFactoryProvider : Provider<ISessionFactory> {
        public class SessionFactoryProvider(IMembershipService service) {
            membershipService = service;
        }
    
        protected override ISessionFactory CreateInstance(IContext context) {
            Configuration nhconfig = new Configuration().Configure();
            nhconfig.AddAssembly(Assembly.GetExecutingAssembly());
            nhconfig.Properties["connection.connection_string"] = buildConnectiongString();
            return nhconfig.BuildSessionFactory();
        }
    
        private string buildConnectionString() {
            return string.Format(membershipService.GetDefaultConnectionString()
                , membershipService.CurrentUser.DatabaseInstanceName
                , membershipService.CurrentUser.Login
                , membershipService.CurrentUser.Password);
        }
    
        private readonly IMembershipService membershipService;
    }
    

    SessionProvider

    public class SessionProvider : Provider<ISession> {
        public class SessionProvider(ISessionFactory factory) {
            sessionFactory = factory;
        }
    
        protected override ISession CreateInstance(IContext context) {
            return sessionFactory.OpenSession();
        }
    
        private readonly ISessionFactory sessionFactory;
    }
    

    事实是,我无法在应用程序启动时实例化IMembershipService.CurrentUser。用户首先要对系统进行身份验证,因此ActivationException

      

    激活ISession

    时出错      

    没有匹配的绑定可用,并且该类型不可自我绑定。

         

    激活路径:

         

    3)将依赖关系ISession注入到InquiriesRepository

    类型的构造函数的参数会话中      

    2)将依赖关系IInquiriesRepository注入到InquiriesManagementPresenter类型的构造函数的参数存储库中

         

    1)要求InquiriesManagementPresenter

         

    建议:

         

    1)确保您已为ISession定义了绑定。

         

    2)如果在模块中定义了绑定,请确保已将模块加载到内核中。

         

    3)确保您没有意外创建多个内核。

         

    4)如果使用构造函数参数,请确保参数名称与构造函数参数名称匹配。

         

    5)如果使用自动模块加载,请确保搜索路径和过滤器正确无误。

    那么,我该怎么做呢?

    欢迎任何设计改进建议。但请记住,我需要它才能正常工作。我将为下一次交付重构。

      

    修改

    看起来我可能会使用上下文/范围依赖注入。

    How to use the additional Ninject Scopes of NamedScope

    但是,我仍然无法弄清楚如何在我的场景中使它工作。

      

    更新

    通过我的阅读,我开始怀疑,与条件约束相比,上下文绑定可能更适合我的需要。

    有什么想法吗?

    与条件绑定相关的每篇文章都讨论条件类型绑定,而不是条件状态绑定。

    在我的场景中,它特别相信它是一个条件状态绑定,因此关于上下文绑定的想法。

    然后,我会有两个绑定。

    1. 在用户通过身份验证之前
    2. 用户通过身份验证后
    3. 所以也许我要么使用延迟注入,这会解决我的问题,因为应用程序启动时不需要ISessionFactory的实例。

      我在这里有点失落......

1 个答案:

答案 0 :(得分:3)

您可以创建条件绑定:

IBindingRoot.Bind<IFoo>().To<Foo>()
    .When(request => request.ParentContext.Kernel.Get<IUserService>().AuthenticatedUser != null);

但我不推荐它; - )

@Pacane

每次请求IFoo时都会执行When条件。它转化为另一个请求,因此成本很高。

此外,此方法仅在有父请求的情况下有效。如果您执行IResolutionRoot.Get<IFoo>(),则会抛出NullReferenceException

您可以通过访问语法提供的内核来解决这个问题。但我不知道它是否会在未来版本的ninject中留在那里......


此外,还有一个应用程序引导机制,可以确保您在完全初始化之后只实例化对象树的某些部分。 (=&gt; authenticated)是一个更好的设计。至少在我看来。