【问题标题】:Parameter based bindings in ninject 2.0ninject 2.0 中基于参数的绑定
【发布时间】:2010-03-18 13:44:31
【问题描述】:

我想根据传递的参数在 ninject 中使用条件绑定。我有如下内容:

public class Subject
{
}

public interface ITarget
{
}

public class Target1 : ITarget
{
}

public class Target2 : ITarget
{
}

现在我需要实例化 ITarget 接口:

    public void MethodName(IKernel kernel)
    {
        ITarget target1 = kernel.Get<ITarget>(new Parameter("name", new Subject(), true)); // Should be instance of Target1
        ITarget target2 = kernel.Get<ITarget>(); // Should be instance of Target2
    }

我无法定义正确的绑定。我尝试了以下方法:

kernel.Bind<ITarget>().To<Target1>().When(Predicate);
kernel.Bind<ITarget>().To<Target2>();

private bool Predicate(IRequest request)
{
    IParameter parameter = request.Parameters.Count == 0 ? null : request.Parameters[0];
    if (parameter == null)
    {
        return false;
    }
    object parameterValue = parameter.GetValue( /*what to put here?*/);
    return parameterValue != null && parameterValue.GetType().IsAssignableFrom(typeof(Subject));
}

但我不知道如何获取传递参数的值。我需要将 IContext 实例传递给 GetValue 方法,但不知道如何获取有效的 IContext 实例。或者也许有更好的方法来完成我的任务?

编辑: BindingMetadata 是解决我的问题的更好方法。详情见Contextual bindings with Ninject 2.0

问候

【问题讨论】:

    标签: parameters ninject conditional-binding contextual-binding


    【解决方案1】:

    IRequest.ParentContext 还不够吗?

    此外,如果您正在寻找的只是使用名称来消除多个实例的歧义 [并且您将能够每次都提供它并且乐于以明确的服务位置方式工作,而不是使用 DI 作为IDeity 意图],那么在 Bind 端有一个 Get 重载,其中包含一个名称和一个 WithName for。

    编辑:在 Reflector 中花了一些时间,但我仍然不太聪明。参数机制似乎是为了覆盖实际绑定发生的 context 中的特定值,而不是作为选择应用绑定的一部分。建立上下文只在内部的一个地方完成(尽管Context 有一个公共 ctor)所以看起来没有一个整洁的工厂。

    您的实际场景是否恰好适合约束机制(其中使用名称进行过滤只是最简单的情况)。即,您能否将您的Get 表达为:

    _kernel.Get<ITarget>( (Ninject.Planning.Bindings.BindingMetadata metadata)=>metadata.Has("x") );
    

    希望@Ian Davis 会尽快出现,因为我也很想知道答案:D

    【讨论】:

    • 不幸的是,ParentBinding 属性在这里为空。我需要像 CurrentContext 这样的东西,但不幸的是没有这样的属性。我知道并使用命名绑定,但我确实需要在生产代码中使用参数。为简洁起见,我在此查询中的示例代码进行了简化。
    • ParentContext,不是 ParentBinding of course
    • 正如你所建议的,BindingMetadata 是解决我的问题的更好方法。
    • @Przemaas:很高兴我在旅途中找到了答案。顺便说一句,对上下文参数的非空检查在 GetValue 调用的低级别被烘焙,但两个最常见的具体实现不使用它。但我敢肯定,正如我们得出的结论,这是设计使然。
    【解决方案2】:

    IIRC 请求可以是多个上下文的一部分。您看到的参数只是您在 Get 调用中指定的参数。在您给出的示例中,您应该能够将 null 作为 IContext 传递以获取您的主题实例。由于您提供的是对象而不是回调,因此该参数将回调构造为 ctx => value -> 因此回调不使用您提供的上下文值。

    【讨论】:

    • 对上下文值有空检查,至少在官方发布的二进制文件中是这样。我没有检查后备箱中的代码。所以当我传递 null 时,我得到了异常。我应该为此提交错误吗?
    • 使用 parameter.ValueCallback(null),GetValue 做空检查,对不起。
    • 这涉及到丑陋的铸造,因为 ValueCallback 不是 IParameter 的成员,但它或多或少都有效。现在实例化 target2 时出现异常,但这与当前问题无关。将为此提出另一个问题
    • @Ian Davis:正如我在 cmets 中对@Przemaas 的评论中提到的那样,GetValue 强制它,但仅有的两种具体参数类型不使用它。很高兴在异常消息或文档中看到一些指导或更改。
    • @Ruben,参数确实使用上下文通过将值传递给回调函数来解析值,但在检查上下文是否为空之后。您是否需要指导何时使用 .When(Func 谓词) 与元数据绑定?你想要一个例外说什么?谢谢!
    猜你喜欢
    • 1970-01-01
    • 2013-02-22
    • 1970-01-01
    • 2011-11-30
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多