Ninject:如何基于依赖链设置绑定

时间:2009-07-19 02:07:40

标签: .net dependency-injection ninject

Ok Dependency Ninja's,这是给你的......

我想根据我从内核请求的类型来改变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使用默认构造函数。

我一定错过了一些明显的东西!

2 个答案:

答案 0 :(得分:3)

听起来好像这里的图层太多了。为什么需要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);
            }
    }
    
  3. 您可以扩展此模型以添加其他属性,以确定是否需要在DatabaseGateway中返回工厂。

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

答案 1 :(得分:1)

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