2

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 使用默认构造函数。

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

4

2 回答 2

3

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

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

  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);
            }
    }
    

You can expand this model to add additional attributes to decided if the factory even needs to be returned in the DatabaseGateway.

It is awkward but may be the best you can do given the number of layers involved.

于 2009-07-21T13:12:15.077 回答
1

This article may help you out as well. Like Jeff said, you'll want to use the With.Parameters.ConstructorArgument(). You can pass in multiple arguments by continuing to chain ConstructorArgument or by using a Dictionary. Hope this helps!

于 2009-09-14T07:38:29.987 回答