Ninject Bind When Ancestor Of Type T

У меня есть цепочка зависимостей, которая выглядит примерно так:

public class CarSalesBatchJob
{
    public CarSalesBatchJob(IFileProvider fileProvider)
    { ... }
}

public class MotorcycleSalesBatchJob
{
    public MotorcycleSalesBatchJob(IFileProvider fileProvider)
    { ... }
}    

public class FtpFileProvider : IFileProvider
{
    public FtpFileProvider(IFtpSettings settings)
    { ... }
}

public class CarSalesFtpSettings : IFtpSettings { ... }
public class MotorcycleSalesFtpSettings : IFtpSettings { ... }

До сих пор я использовал привязки, основанные на соглашениях, но это уже недостаточно хорошо, потому что у меня есть более одна реализация для IFtpSettings. Поэтому я решил использовать некоторые контекстные привязки. На первый взгляд kernel.Bind<>().To<>().WhenInjectedInto<>()выглядел многообещающе, но это помогает только на первом уровне, а это означает, что если бы у меня были CarSalesFtpFileProviderи MotorcycleSalesFtpProvider, я мог бы сделать это:

kernel.Bind<IFtpSettings>().To<CarSalesFtpSettings>()
    .WhenInjectedInto<CarSalesFtpFileProvider>();
kernel.Bind<IFtpSettings>().To<MotorcycleSalesFtpSettings>()
    .WhenInjectedInto<MotorcycleSalesFtpFileProvider>();

Но кажется довольно глупым создание двух конкретных реализаций FtpFileProvider, которые действительно отличаются только тем, какие настройки я хочу, чтобы они использовали. Я видел, что есть метод с именем WhenAnyAnchestorNamed(string name). Но этот маршрут требует, чтобы я добавлял атрибуты и магические строки в свои пакетные задания, что меня не впечатляет.

Я также заметил, что существует простой старый метод .When(Func)для операторов привязки, поэтому я придумал это как свои операторы привязки:

//at this point I've already ran the conventions based bindings code so I need to unbind
kernel.Unbind<IFtpSettings>();
kernel.Bind<IFtpSettings>().To<CarSalesFtpSettings>()
    .When(r => HasAncestorOfType<CarSalesBatchJob>(r));
kernel.Bind<IFtpSettings>().To<MotorcycleSalesFtpSettings>()
    .When(r => HasAncestorOfType<MotorcycleSalesBatchJob>(r));

// later on in the same class
private static bool HasAncestorOfType<T>(IRequest request)
{
    if (request == null)
        return false;

    if (request.Service == typeof(T))
        return true;

    return HasAncestorOfType<T>(request.ParentRequest);
}

Итак, если конструктор запрашивает IFtpSettings, мы рекурсивно поднимаемся по дереву запросов, чтобы увидеть, соответствуют ли какие-либо из запрошенных служб/типов в цепочке предоставленному типу (CarSalesBatchJob или MotorcycleSalesBatchJob), и если да, то возвращается true. Если мы дойдем до вершины цепочки, мы вернем false.

Извините за длинное пояснение.

Вот мой вопрос: Есть ли причина, почему я не должен подходить к проблеме таким образом?Считается ли это дурным тоном? Есть ли лучший способ найти типы запросов предков? Должен ли я реструктурировать свою цепочку классов/зависимостей в более «приемлемом» стиле?

11
задан viggity 6 June 2012 в 20:50
поделиться