Виндзорская регистрация компонентов на основе общего интерфейса
Я пытаюсь зарегистрировать несколько типов, которые используют один и тот же интерфейс 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>());
ключевой момент - как вы регистрируете свои типы настроек. если я не покрыл ваше использование, пожалуйста, не могли бы вы предоставить дополнительную информацию.
надеюсь это поможет