【问题标题】:Inject value into injected dependency将值注入到注入的依赖项中
【发布时间】:2011-01-10 08:37:15
【问题描述】:

我有这样的事情:

class Root
{
    public Root(IDependency dep)
    {}
}
class Dependency:IDependency
{
    public Dependency(int val)
    {}
}

我正在尝试使用 ninject 获取对 Root 的引用。 所以我是这样配置的

var module = new InlineModule(mod => mod.Bind<IDependency>().To<Dependency>());

var kernel = new StandardKernel(module);

我想向 Dependency 注入一些 'val' 值,该值仅在从 ninject 获取 Root 引用时才知道。

我想做的是这样的:

Kernel.Instance.Get<Root>(With.Parameters.ConstructorArgument("val", 12));

使用 ninject 1.0 可以实现这样的事情吗?

【问题讨论】:

    标签: dependency-injection ninject


    【解决方案1】:

    默认情况下,上下文中的Parameters.ConstructorArgument 仅深一层。

    将参数向下传递多个级别的一种方法是使用 ContextParameter,但随后需要抓住它并说 - 现在我们将使用它作为 在这种情况下是 ConstructorArgument。一种这样的构造是提供者。见this dojo page for details of Providers

    所以你可以这样做:

        class DependencyProvider : SimpleProvider<Dependency>
        {
            protected override Dependency CreateInstance( IContext context )
            {
                return new Dependency( (int)context.ParentContext.Parameters.GetOne<ContextVariableParameter>( "masterVal" ).Value );
            }
        }
    
        public static void Main()
        {
            var module = new InlineModule(
                mod => mod.Bind<IDependency>().ToProvider( new DependencyProvider() )
            );
    
            var kernel = new StandardKernel( new[  ] {module} );
    
            Root root = kernel.Get<Root>( With.Parameters.ContextVariable( "masterVal", 12 ) ); 
        }
    

    或者你可以按如下方式管理:

        class RootProvider : SimpleProvider<Root>
        {
            protected override Root CreateInstance( IContext context )
            {
                return new Root( context.Kernel.Get<Dependency>( With.Parameters.ConstructorArgument("val", ( int )context.Parameters.GetOne<ContextVariableParameter>("masterVal").Value )));
            }
        }
    
        public static void Main()
        {
            var module = new InlineModule(
                mod => mod.Bind<IDependency>().To<Dependency>(), // Optional if ImplictSelfBinding is on
                mod => mod.Bind<Root>().ToProvider( new RootProvider() )
            );
    
            var kernel = new StandardKernel( new[] {module} );
    
            Root root = kernel.Get<Root>( With.Parameters.ContextVariable( "masterVal", 12 ) ); 
        }
    

    当您考虑这个问题时,请考虑the points I make in this point re separating the concerns if configuration from object binding in this response

    【讨论】:

    • 我想我可以做得更简单一点:Bind().To().WithConstructorArgument("val", (IContext cont) => cont.ParentContext. Parameters.Get("val"));但我不喜欢使用 ParentContext。 :( 它
    • @Silviu:试试看——越短越好。对我来说,直接按照您的要求进行操作似乎是有道理的,但在我正在尝试的情况下,我无法让它为我工作。
    • @Silviu:作为Bind 锻炼的一部分,你有没有做到这一点?如果是这样,如果你想把一些有用的东西放到 cmets 中,我会把它放到示例中。
    • 抱歉回复晚了。我尝试使用父上下文。有效。不是很自豪。 :D 可能是我的观点的错误,但是当我定义一个绑定时,我告诉 Ninject 使用一些键值对。在那一刻,出于某种原因,我希望为整个依赖链考虑这些值,因为那是正在使用的上下文。事实上,我认为上下文代表了 Ninject 构建事物的媒介。因此,一旦为某个类定义,它应该为所有部门使用该上下文。每个 dep 的绑定都添加到相同的上下文中。
    • 我真的不喜欢那个父级的东西。感觉我需要在绑定级别了解太多关于依赖层次结构的信息。我的意思是,如果我在 Root 和 Dependency 之间放置另一层呢?然后我将不得不修改依赖项到 context.ParentContext.ParentContext 的绑定,这是一些非常丑陋的耦合。
    【解决方案2】:

    使用 Ninject 3 IParameters(ConstructorArgument 是其中之一)现在将简单地“继承”给具有 ShouldInherit == true 的子请求(请参阅 here)。

    这个问题的解决方案现在可以很简单:

    IResolutionRoot.Get<Root>(new ConstructorArgument("val", 12, true));
    

    ConstructorArguments 构造函数中的trueShouldInherit 设置为true。另见here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-20
      • 1970-01-01
      • 2014-09-23
      • 2011-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多