Виндзорская регистрация компонентов на основе общего интерфейса

Я пытаюсь зарегистрировать несколько типов, которые используют один и тот же интерфейс ISetting с виндзорским контейнером.

Пояснение: ISetting интерфейс не требует никакой реализации. Его единственная цель - помочь найти типы настроек в сборке. В противном случае эти типы настроек никак не связаны друг с другом, ни в форме, ни в форме.

Обычно я создавал бы эти типы один за другим с кодом, следующим образом:

var settingsManager = new SettingsManager();
var applicationSettings = settingsManager.LoadSettings<ApplicationSettings>();
var emailSettings = settingsManager.LoadSettings<EmailSettings>();

Но я хотел бы зарегистрировать эти компоненты по соглашению, поэтому мне не нужно делать это вручную.

Пока у меня есть следующий код в одном из WindsorInstallers:

    container.Register( Classes.FromAssemblyContaining<ISetting>()
                                   .BasedOn<ISetting>()
                                   ...help...
                                   );

Пояснение: настройка будет использоваться в классе как конкретный тип (см. Ниже)

public class Service2
{
    private readonly EmailSettings _settings;

    public Service2(EmailSettings settings)
    {
        _settings = settings;
    }

    public void Awesome()
    {
        Console.WriteLine(_settings.Value);
    }
}

Моя цель: несмотря на то, что я мог бы вставлять все типы настроек в контейнер один за другим, я ищу решение, в котором я мог бы найти и зарегистрировать все типы, наследуемые от ISetting используя одно (возможно, два) утверждения.

1 ответ

Решение

Это зависит от того, как вы хотите его использовать (ввести его)

вот возможное решение

container.Register(
Classes
    .FromThisAssembly()
    .BasedOn<ISettings>()
    .WithServiceSelf()  //for way 3
    .WithServiceFirstInterface() //way 1 & 2
    .Configure(c => c.Named(c.Implementation.Name)) //way 1 & 2
    );

Способ 1 - решить напрямую - я не думаю, что вы будете использовать этот

в вашем примере вы получаете настройки напрямую, вы можете использовать именованный параметр с контейнером следующим образом

var settings = container.Resolve<ISettings>("EmailSettings");

при таком разрешении настроек мы использовали именованный параметр, чтобы выбрать правильную реализацию.

Способ 2 - инъекция с использованием названного параметра

в этом случае у нас есть сервис следующим образом (снова угадывая возможное использование)

public class Service1
{
    private readonly ISettings _emailSettings;

    public Service1(ISettings emailSettings)
    {
        _emailSettings = emailSettings;
    }

    public void Awesome()
    {
        Console.WriteLine(_emailSettings.Value);
    }
}

чтобы это работало, нам нужно зарегистрировать этот тип, чтобы использовать именованный параметр с параметром конструктора, который выглядит следующим образом:

//using a named parameter
container.Register(
    Component.For<Service1>().ImplementedBy<Service1>()
    .DependsOn(Dependency.OnComponent(typeof(ISettings), "EmailSettings")));

Зависит от того, что ищет параметры / параметры ctor для добавления. затем он использует именованную реализацию.

способ 3 - мы используем прямой тип

этот возможный способ предполагает, что служба знает, что ей требуется конкретный тип, например:

public class Service2
{
    private readonly EmailSettings _settings;

    public Service2(EmailSettings settings)
    {
        _settings = settings;
    }

    public void Awesome()
    {
        Console.WriteLine(_settings.Value);
    }
}

регистрация для этого такая же, как обычно

//using the actual type
container.Register(Component.For<Service2>().ImplementedBy<Service2>());

ключевой момент - как вы регистрируете свои типы настроек. если я не покрыл ваше использование, пожалуйста, не могли бы вы предоставить дополнительную информацию.

надеюсь это поможет

Другие вопросы по тегам