【问题标题】:Ninject: Howto setup Bindings based upon Dependency ChainNinject:如何根据依赖链设置绑定
【发布时间】:2009-07-19 02:07:40
【问题描述】:

Ok Dependency Ninja,给你一个……

我想根据我从内核请求的类型更改 Ninject 构建依赖项的方式。

我有一个带有以下构造函数的 DbConnectionFactory 类:

    public DbConnectionFactory()
        : this(MyDatabase.ConnectionString)
    {
    }

    public DbConnectionFactory(string connectionString)
        : this(DbProviderFactories.GetFactory("System.Data.SqlClient"), connectionString)
    {
    }

对于“默认”绑定,我希望 Ninject 使用无参数构造函数:

        this.Bind<IDbConnectionFactory>().To<DbConnectionFactory>();

我的代码中的某些类需要 Ninject 来提供 connectionString 参数。我尝试像这样设置绑定:

        this.Bind<IDbConnectionFactory>().To<DbConnectionFactory>().Only(
            When.Context.InstanceOf(typeof(IRepository))).WithArgument(
            "connectionString", MyOtherDatabase.ConnectionString);

但是,我只让 Ninject 使用默认构造函数。

我一定遗漏了一些明显的东西!

【问题讨论】:

    标签: .net dependency-injection ninject


    【解决方案1】:

    听起来好像这里的层太多了。为什么需要 DatabaseGateway?为什么不使用 ADO.NET 提供程序工厂来创建连接(也可以通过 Ninject 连接它们)来直接管理连接?或者更好的是,使用存储库模式使用 NHibernate 之类的东西并使用它来映射对象?

    无论如何,总是使用更长的构造函数并根据情况交替传入 MyDatabase.ConnectionString 或 MyOtherDatabase.ConnectionString 怎么样?您可以使用herehere 所述的提供程序,但除非绝对必要,否则我会尽量避免使用它们:

    1. 定义两个新属性

      public class DefaultDatabaseAttribute : Attribute {}
      public class OtherDatabaseAttribute : Attribute {}
      
    2. 在构造函数中使用适当的属性装饰 DatabaseGateway 参数

      public class OneRepository : IRepository
      {
          public OneRepository([DefaultDatabase]DatabaseGateway factory)
          {
          }
      }
      
      public class TwoRepository : IRepository
      {
          public TwoRepository([OtherDatabase]DatabaseGateway factory)
          {
          }
      }
      

      你的提供者看起来像:

      public class DatabaseGatewayProvider : SimpleProvider<DatabaseGateway>
      {
              protected override DatabaseGateway CreateInstance(Ninject.Core.Activation.IContext context)
              {
                  IDbConnectionFactory factory;
                  if (context.Member.IsDefined(typeof(DefaultDatabaseAttribute), false))
                  {
                      factory = context.Kernel.get<IDbConnectionFactory>(With.Parameters.ConstructorArgument("connectionString", MyDatabase.ConnectionString)));
                  }
                  else if (context.Member.IsDefined(typeof(OtherDatabaseAttribute), false))
                  {
                      factory = context.Kernel.get<IDbConnectionFactory>(With.Parameters.ConstructorArgument("connectionString", MyOtherDatabase.ConnectionString)));
                  }
      
                  return new DatabaseGateway(factory);
              }
      }
      

    您可以扩展此模型以添加其他属性来决定是否需要在 DatabaseGateway 中返回工厂。

    这很尴尬,但考虑到所涉及的层数,这可能是您能做的最好的事情。

    【讨论】:

      【解决方案2】:

      这个article 也可以帮助你。就像 Jeff 说的,你会想要使用 With.Parameters.ConstructorArgument()。您可以通过继续链接 ConstructorArgument 或使用字典来传递多个参数。希望这会有所帮助!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多