2015-05-27 184 views
0

在我的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

什麼是最好的辦法,爲什麼?

回答

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) 
{ 
    ... 
}