Windsor组件注册基于通用接口

Val*_*era 2 .net castle-windsor ioc-container

我正在尝试注册ISetting与Windsor容器共享相同接口的几种类型.

澄清:ISetting界面不需要任何实现.它的唯一目的是帮助在装配体中找到设置类型.否则,这些设置类型不以任何方式,形状或形式相互关联.

通常我会逐行创建这些类型的代码:

var settingsManager = new SettingsManager();
var applicationSettings = settingsManager.LoadSettings<ApplicationSettings>();
var emailSettings = settingsManager.LoadSettings<EmailSettings>();
Run Code Online (Sandbox Code Playgroud)

但我想按惯例注册这些组件,所以我不必手动完成.

到目前为止,我在WindsorInstallers中有以下代码:

    container.Register( Classes.FromAssemblyContaining<ISetting>()
                                   .BasedOn<ISetting>()
                                   ...help...
                                   );
Run Code Online (Sandbox Code Playgroud)

澄清:设置将在类中用作具体类型(见下文)

public class Service2
{
    private readonly EmailSettings _settings;

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

    public void Awesome()
    {
        Console.WriteLine(_settings.Value);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的目标:尽管我可以逐个将所有设置类型注入容器,但我正在寻找一种解决方案,我可以找到并注册从ISetting使用一个(可能是两个)语句继承的所有类型.

dbo*_*nes 5

这取决于你想如何使用它(注入它)

这是一个可能的解决方案

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

方式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);
    }
}
Run Code Online (Sandbox Code Playgroud)

要使其工作,我们需要注册此类型以使用带有构造函数参数的命名参数,如下所示:

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

这取决于寻找属性/ ctor params注入.然后它使用命名的实现.

方式3 - 我们使用直接类型

这种可能的方式假设服务知道它需要具体类型,例如:

public class Service2
{
    private readonly EmailSettings _settings;

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

    public void Awesome()
    {
        Console.WriteLine(_settings.Value);
    }
}
Run Code Online (Sandbox Code Playgroud)

这个注册与往常一样

//using the actual type
container.Register(Component.For<Service2>().ImplementedBy<Service2>());
Run Code Online (Sandbox Code Playgroud)

关键部分是如何注册您的设置类型.如果我没有满足您的使用,请您提供更多信息.

希望这可以帮助