根据配置解决依赖关系

时间:2015-05-27 09:08:02

标签: dependency-injection castle-windsor ioc-container

在我的Windows服务应用程序中,我需要在服务启动时使用配置解析组件。我使用Castle Windsor作为我的IoC容器。

应用程序如下:

public class RootComponent : IRootComponent {
    public RootComponent (IDataProvider1 provider1, IDataProvider2 provider2)
    {
        this.provider1 = provider1;
        this.provider2 = provider2;
    }

    ...
}

public class DataProvider1 : IDataProvider1
{
    ...

    public DataProvider1 (IDbHelper dbHelper)
    {
        this.dbHelper = dbHelper;
    }

    ...
}

public class DataProvider2 : IDataProvider2
{
    ...

    public DataProvider1 (IDbHelper dbHelper)
    {
        this.dbHelper = dbHelper;
    }

    ...
}

public interface IDbHelper
{
    IDbConnection GetNewConnection();
    DbParameter CreateDbParameter(string paramName, object paramValue);
    string GetCommandString(string commandName);
}

public class MsSqlDbHelper : IDbHelper
{
    ...

    public MsSqlDbHelper(string connectionString)
    {
        this.connectionString = connectionString;
    }

    ...
}

public class PostgreDbHelper : IDbHelper
{
    ...

    public PostgreDbHelper(string connectionString)
    {
        this.connectionString = connectionString;
    }

    ...
}

我想在服务构造函数中注册依赖项,在OnStart方法中读取配置并根据它解析正确的IDbHelper:

public partial class MyWindowsService : ServiceBase
{
    public MyWindowsService()
    {
        InitializeComponent();

        this.container = new WindsorContainer();
        RegisterDependencies();
    }

    private void RegisterDependencies()
    {
        container.Register(
            Classes.FromAssemblyInThisApplication().BasedOn<IRootComponent>().WithServiceFromInterface(), 
            Classes.FromAssemblyInThisApplication().BasedOn<IDataProvider1>().WithServiceFromInterface(),
            Classes.FromAssemblyInThisApplication().BasedOn<IDataProvider2>().WithServiceFromInterface(),
            Classes.FromAssemblyInThisApplication().BasedOn<IDbHelper>().WithServiceFromInterface()
                .ConfigureFor<MsSqlDbHelper>(
                    registration => {
                        registration.DependsOn(Dependency.OnValue<string>(ConnectStringProvider.GetConnectionString("connectString1")));
                        registration.Named("msSql");
                    })
                .ConfigureFor<PostgreDbHelper>(
                    registration => {
                        registration.DependsOn(Dependency.OnValue<string>(ConnectStringProvider.GetConnectionString("connectString2")));
                        registration.Named("postgreSql");
                    }));
    }

    protected override void OnStart(string[] args)
    {
        ResolveDependencies();
    }

    private void ResolveDependencies()
    {
        // Helper properties contain "msSql" or "postgreSql" value
        root = container.Resolve<IRootComponent>(Config.Provider1Helper, Config.Provider2Helper);
    }

    ...
}

我看到了如何解析配置的IDbHepler的三个选项:

  1. 类型工厂设施
  2. 儿童容器
  3. 实施IHandlerSelector
  4. 最好的方法是什么?为什么?

1 个答案:

答案 0 :(得分:0)

解决方案比我预期的简单。 DynamicParameters就是我所需要的:

private void RegisterDependencies()
{
    container.Register(
        Classes.FromAssemblyInThisApplication().BasedOn<IRootComponent>().WithServiceFromInterface(), 
        Classes.FromAssemblyInThisApplication().BasedOn<IDataProvider1>().WithServiceFromInterface()
            .Configure(registration => registration.DynamicParameters((kernel, parameters) =>
                    {
                        IDbHelper dbHelper = kernel.Resolve<IDbHelper>(Config.Provider1Helper);
                        parameters.Add("dbHelper", dbHelper);
                        return k => k.ReleaseComponent(dbHelper);
                    })),
        Classes.FromAssemblyInThisApplication().BasedOn<IDataProvider2>().WithServiceFromInterface(),
            .Configure(registration => registration.DynamicParameters((kernel, parameters) =>
                    {
                        IDbHelper dbHelper = kernel.Resolve<IDbHelper>(Config.Provider2Helper);
                        parameters.Add("dbHelper", dbHelper);
                        return k => k.ReleaseComponent(dbHelper);
                    })),
        Classes.FromAssemblyInThisApplication().BasedOn<IDbHelper>().WithServiceFromInterface()
            .ConfigureFor<MsSqlDbHelper>(
                registration => {
                    registration.DependsOn(Dependency.OnValue<string>(ConnectStringProvider.GetConnectionString("connectString1")));
                    registration.Named("msSql");
                })
            .ConfigureFor<PostgreDbHelper>(
                registration => {
                    registration.DependsOn(Dependency.OnValue<string>(ConnectStringProvider.GetConnectionString("connectString2")));
                    registration.Named("postgreSql");
                }));
}

protected override void OnStart(string[] args)
{
    // Helper properties should contain "msSql" or "postgreSql" value
    // take configuration from arguments
    Config.Provider1Helper = UseMsSql(args, 0) ? "msSql" : "postgreSql";
    Config.Provider2Helper = UseMsSql(args, 1) ? "msSql" : "postgreSql";

    ResolveDependencies();
}

private void ResolveDependencies()
{
    root = container.Resolve<IRootComponent>();
}

private bool UseMsSql(string[] args, int argNumber)
{
    ...
}