2

我们在NinjectModule某个IInspection接口中定义了一个多重绑定,如下所示:

private void BindCodeInspectionTypes()
{
    var inspections = Assembly.GetExecutingAssembly()
                              .GetTypes()
                              .Where(type => type.BaseType == typeof (InspectionBase));

    // multibinding for IEnumerable<IInspection> dependency
    foreach (var inspection in inspections)
    {
        var binding = Bind<IInspection>().To(inspection).InSingletonScope();
        binding.Intercept().With<TimedCallLoggerInterceptor>();
        binding.Intercept().With<EnumerableCounterInterceptor<InspectionResultBase>>();
    }
}

所以拦截器代理类型将是 for IInspection。然而,一些inspection类型实现了一个IParseTreeInspection接口,它扩展 IInspection了:

public interface IParseTreeInspection : IInspection
{
    ParseTreeResults ParseTreeResults { get; set; }
}

这造成的问题是这段代码消耗了拦截器 - 可以理解的是,注入的代理类型似乎不知道任何关于 的内容IParseTreeInspection,所以这个foreach循环甚至不会迭代一次:

var enabledParseTreeInspections = _inspections.Where(inspection => 
    inspection.Severity != CodeInspectionSeverity.DoNotShow 
 && inspection is IParseTreeInspection);

foreach (var parseTreeInspection in enabledParseTreeInspections)
{
    (parseTreeInspection as IParseTreeInspection).ParseTreeResults = parseTreeWalkResults;
}

有什么方法可以进行多重绑定IInspection(即构造函数注入IEnumerable<IInspection>并且仍然能够IParseTreeInspection在 Ninject 注入拦截器时告诉实例?

4

1 回答 1

0

这是一种方法:

foreach (var inspection in inspections)
{
    if (typeof (IParseTreeInspection).IsAssignableFrom(inspection))
    {
        var binding = Bind<IParseTreeInspection>()
            .To(inspection)
            .InSingletonScope()
            .Named(inspection.FullName);

        binding.Intercept().With<TimedCallLoggerInterceptor>();
        binding.Intercept().With<EnumerableCounterInterceptor<InspectionResultBase>>();

        Bind<IInspection>().ToMethod(
            c => c.Kernel.Get<IParseTreeInspection>(inspection.FullName));
    }
    else
    {
        var binding = Bind<IInspection>().To(inspection).InSingletonScope();
        binding.Intercept().With<TimedCallLoggerInterceptor>();
        binding.Intercept().With<EnumerableCounterInterceptor<InspectionResultBase>>();
    }
}

此代码检查该类型是否可分配 from IParseTreeInspection,即它是否实现IParseTreeInspection,如果是,它会创建一个命名绑定 fromIParseTreeInspection到该类型并在此处配置拦截。这将确保代理对象(由拦截器创建)将实现IParseTreeInspection. 然后它创建另一个绑定IInspection到委托调用,该调用将使用内核IParseTreeInspection通过第一个绑定(使用绑定名称)来解析。

于 2016-07-11T20:14:25.973 回答