【问题标题】:Providing Ninject with constructor dependencies it can't resolve?为 Ninject 提供无法解决的构造函数依赖项?
【发布时间】:2012-01-26 07:16:08
【问题描述】:

免责声明:我对 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>();
    }
} 

现在,假设一些运行时逻辑涉及派生提供给ClassAstring runtimeDependency。我应该如何为 Ninject 提供runtimeDependency,以便它可以为ClassB 提供ClassA 的实例?

字符串只会被确定一次,所以我不需要为每个实例注入一个新值。

【问题讨论】:

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


    【解决方案1】:

    一种方法是通过一种方法提供ClassA。另外请记住,使用 Ninject 2,您不需要模块,可以直接在内核中进行绑定。

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

    我真的很想知道什么时候你的运行时变量可用并且它的作用域。

    【讨论】:

    • 我很高兴你提到了变量的生命周期和范围;如果变量在绑定时还不存在怎么办? (我相信我应该尽早在一个公共位置初始化所有绑定。)
    • @robjb:这似乎更像是一个设计问题,而不是一个 ninject 问题。没有更多的上下文,很难说。您只确定字符串一次,因此很可能需要您在设置之后执行 all 绑定。请记住,我绝不是 Ninject 专家。
    【解决方案2】:

    这里有几个选项,具体取决于您的设计和具体问题。第一个也是最简单的解决方案是在您向 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>();
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-06
      • 1970-01-01
      • 1970-01-01
      • 2019-03-23
      • 2012-01-04
      • 2014-09-05
      • 2012-08-19
      • 2015-01-03
      相关资源
      最近更新 更多