We have a multi-binding defined in a NinjectModule for some IInspection interface, like this:
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>>();
}
}
So the interceptor proxy types will be for IInspection. However some of the inspection types implement an IParseTreeInspection interface, which extends IInspection:
public interface IParseTreeInspection : IInspection
{
ParseTreeResults ParseTreeResults { get; set; }
}
The problem this creates is with this bit of code that consumes the interceptors - the injected proxy types understandably don't seem to know anything about IParseTreeInspection, so this foreach loop doesn't iterate even once:
var enabledParseTreeInspections = _inspections.Where(inspection =>
inspection.Severity != CodeInspectionSeverity.DoNotShow
&& inspection is IParseTreeInspection);
foreach (var parseTreeInspection in enabledParseTreeInspections)
{
(parseTreeInspection as IParseTreeInspection).ParseTreeResults = parseTreeWalkResults;
}
Is there any way I can multi-bind IInspection (i.e. constructor-inject IEnumerable<IInspection>) and still be able to tell IParseTreeInspection instances when Ninject is injecting interceptors?
Here is one way to do it:
This code checks if the type is assignable from
IParseTreeInspection, i.e., it implementsIParseTreeInspection, and if so, it creates a named binding fromIParseTreeInspectionto this type and configures the interception here. This will make sure that the proxy objects (created by the interceptor) will implementIParseTreeInspection. Then it creates another binding fromIInspectionto a delegate invocation that would use the kernel to resolveIParseTreeInspectionvia the the first binding (using the binding name).