Как получить доступ к расширенному интерфейсу на перехватчике?

У нас есть множественная привязка, определенная в 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>>();
    }
}

Таким образом, типы прокси-перехватчиков будут для 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 внедряет перехватчики?


person Mathieu Guindon    schedule 11.07.2016    source источник
comment
unrelated, просто хотел поздравить вас с MVP, просматривал ваш профиль и увидел, что вы получили его в этом году... Было ли это сложным собеседованием/процессом подачи заявки после номинации?   -  person Kubie    schedule 24.10.2018
comment
@Куби, спасибо! на заполнение формы ушло несколько дней (вам нужно перечислить все ваши взносы за год, я должен обновить свои материалы на этот год), затем было телефонное интервью, .. затем я проснулся 1 января с поздравлением по электронной почте от Microsoft! знак равно   -  person Mathieu Guindon    schedule 24.10.2018


Ответы (1)


Вот один из способов сделать это:

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

Этот код проверяет, является ли тип назначаемым из IParseTreeInspection, т. е. реализует IParseTreeInspection, и если да, то создает именованную привязку из IParseTreeInspection к этому типу и настраивает здесь перехват. Это гарантирует, что прокси-объекты (созданные перехватчиком) будут реализовывать IParseTreeInspection. Затем он создает еще одну привязку из IInspection к вызову делегата, который будет использовать ядро ​​для разрешения IParseTreeInspection через первую привязку (используя имя привязки).

person Yacoub Massad    schedule 11.07.2016