为Ninject提供构造函数依赖,它无法解决?

时间:2011-12-22 17:07:18

标签: c# .net dependency-injection inversion-of-control ninject

免责声明:我对DI和IoC都很陌生,请原谅任何严重的误解。

考虑一个需要实现ClassB的对象的IClassA。 Ninject应该能够将ClassA的实例注入ClassB的构造函数中,假设它可以构造ClassA的实例:

public class ClassA : IClassA
{
    public ClassA(string runtimeDependency) { /* ... */ }
}

public class ClassB : IClassB
{
    public ClassB(IClassA depA) { /* ... */ }
}

public sealed class TestBootstrapModule : NinjectModule
{
    public override void Load()
    {
        Bind<IClassA>().To<ClassA>();
        Bind<IClassB>().To<ClassB>();
    }
} 

现在,假设某些运行时逻辑涉及派生到string runtimeDependency的{​​{1}}。我应该如何向Ninject提供ClassA,以便它可以runtimeDependency提供ClassB个实例?

字符串只会被确定一次,所以我不必担心在每个实例中注入一个新值。

2 个答案:

答案 0 :(得分:2)

执行此操作的方式是通过方法提供ClassA。还要记住,使用Ninject 2,您不需要模块,可以直接在内核中进行绑定。

Bind<IClassA>().ToMethod(_ => 
  {
     // do something interesting with a runtimeDependancy
     return new ClassA(someInterestingVariable);
  });

当你的你的运行时变量可用且它的范围是时,我真的正在努力。

答案 1 :(得分:0)

根据您的设计和具体问题,这里有一些选项。第一个最简单的解决方案是在您从Ninject请求服务时提供价值

Kernel.Get<IClassA>("runtimeDependencyValue");

如果不可能,那么事情会变得有趣。我以前解决这个问题的方法是实际创建与System.String本身的上下文绑定。

如果我想绑定连接字符串,我将创建一个自定义属性:

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class ConnectionStringAttribute : Attribute     
{
    /// <summary>
    /// Denotes the setting that you want to populate the given property with.
    /// </summary>
    public string SettingName { get; private set; }

    public ConnectionStringAttribute(string configSettingName = "")
    {
        SettingName = configSettingName;
    }
}

然后我像这样装饰我的服务构造函数:

public class ClassA : IClassA
{
    public ClassA([ConnectionString("AppDB")] string runtimeDependency) { /* ... */ }
}

最后,我的绑定看起来像这样:

Bind<string>()
    .ToMethod(ctx => 
    {
        var attr = (ConnectionStringAttribute)context.Request.Target.GetCustomAttributes(typeof(ConnectionStringAttribute), true).First();
        string settingName = string.IsNullOrEmpty(attr.SettingName) ? context.Request.Target.Name : attr.SettingName;
        return ConfigurationManager.ConnectionStrings[settingName].ConnectionString;
    })
    .WhenTargetHas<ConnectionStringAttribute>();

你明白了。希望这会有所帮助:)