将值注入到已注入的依赖项中

8

我有一个类似这样的东西:

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

我希望在从ninject获取Root引用时,向依赖项注入某些“val”值,该值仅在此时已知。
我的想法是这样的:
Kernel.Instance.Get<Root>(With.Parameters.ConstructorArgument("val", 12));

“是否可以使用Ninject 1.0实现这样的功能?”
2个回答

8

默认情况下,上下文中的Parameters.ConstructorArgument 仅向下传递一个级别。

将参数传递到多个级别的一种方法是使用ContextParameter,但是需要有东西抓住它并说 - 现在我们将在这种情况下将其用作ConstructorArgument。其中一种构造是Providers。请参见此dojo页面了解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 ) ); 
    }

在考虑这个问题时,请参考我在此回答中所提到的关于将配置与对象绑定分离的观点


我真的不喜欢那个父级别的东西。感觉我需要在绑定层面了解太多关于依赖关系层次结构的东西。我的意思是,如果我在根和依赖之间再加一层呢?那么我就必须修改依赖项到context.ParentContext.ParentContext的绑定,这是一种非常丑陋的耦合。 - Silviu
你需要的是名称方面的东西吗?还是你可以重新调整一下你的需求来符合这个方向?请查看https://dev59.com/THI95IYBdhLWcg3w5iY4#2112070。 - Ruben Bartelink
@Ruben Bartelink - 感谢您的回答。我有一个类似的问题(https://dev59.com/AGsy5IYBdhLWcg3w0RM4),Remo已经提供了一个答案...但是我在将属性构造函数参数的值传递给其绑定过滤器的构造函数参数时遇到了麻烦。您能否在那个问题中提供一个示例? - one.beat.consumer
@one.beat.consumer 很遗憾,仅从评论中很难理解您的意思。如果 Remo Gloor 无法解决问题,我建议您提出另一个带有失败示例的问题,抱歉! - Ruben Bartelink
@Ruben Bartelink - 搞定了。我想我是在 Func<> 签名上犯难了。我猜我喝的咖啡不够。那个,我需要在 Attribute 类中将值公开为属性。搞定了-现在我正在尝试将带标记的 Flags 枚举值解析成单独的标记。 :( - one.beat.consumer
显示剩余5条评论

2

使用 Ninject 3,IParameterConstructorArgument 是其中之一)现在将在子请求中简单地“继承”,当它们具有 ShouldInherit == true 时(请参见此处)。

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

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

ConstructorArgument的构造函数中,true设置ShouldInherittrue。详见此处


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接