2013-08-02 2 views
19

Durante la registrazione dei componenti in Castle Windsor, come si associa un'implementazione specifica di un'interfaccia a un componente che ha una dipendenza da tale interfaccia. So in anticipo quale implementazione deve essere utilizzata dal componente.Castle Windsor - implementazione multipla di un'interfaccia

Ad esempio, ho creato un'applicazione di console di esempio basata sul codice di diversi blog ed esercitazioni.

Di seguito è riportato il codice.

public interface IReport 
{ 
    void LogReport(); 
} 

public interface ILogger 
{ 
    string Log(); 
} 

public class FileLogger : ILogger 
{ 
    public string Log() 
    { 
     return "Logged data to a file"; 
    } 
} 

public class DatabaseLogger : ILogger 
{ 
    public string Log() 
    { 
     return "Logged data to a database"; 
    } 
} 

public class McAfeeService : IReport 
{ 
    private readonly ILogger _logger; 

    public McAfeeService(ILogger logger) 
    { 
     this._logger = logger; 
    } 

    public void LogReport() 
    { 
     string getLogResult = this._logger.Log(); 

     Console.WriteLine("McAfee Scan has " + getLogResult); 
    }   
} 

public class NortonService : IReport 
{ 
    private readonly ILogger _logger; 

    public NortonService(ILogger logger) 
    { 
     this._logger = logger; 
    } 

    public void LogReport() 
    { 
     string getLogResult = this._logger.Log(); 

     Console.WriteLine("Norton Scan has " + getLogResult); 
    } 
} 

class Program 
{ 
    private static IWindsorContainer container; 

    static void Main(string[] args) 
    { 
     // Register components 
     container = new WindsorContainer(); 

     container.Register(Component.For<IReport>().ImplementedBy<NortonService>()); 
     container.Register(Component.For<ILogger>().ImplementedBy<FileLogger>()); 

     IReport service = container.Resolve<IReport>(); 
     service.LogReport(); 

     Console.ReadLine(); 
    } 
} 

Desidero che NortonService utilizzi sempre un Filelogger e McAfeeService per utilizzare un Database Logger.

Nel suddetto programma non riesco a associare NortonService a FileLogger.

Come fare?

risposta

2

La mia risposta forse non il migliore, potete utilizzare il metodo denominazione per risolvere più applicazione:

container.Register(Component.For(typeof(ILogger)) 
      .ImplementedBy(typeof(FileLogger)) 
      .Named("FileLoggerIoC") 
      .LifestylePerWebRequest() , 
      Component.For(typeof(ILogger)) 
      .ImplementedBy(typeof(DatabaseLogger)) 
      .Named("DatabaseLoggerIoC") 
      .LifestylePerWebRequest()); 

Nelle tue funzioni di chiamata, è necessario risolvere per nome: -

var fileLog = container.Resolve("FileLoggerIoC", typeof(ILogger)); 
var DbLog = container.Resolve("DatabaseLoggerIoC", typeof(ILogger)); 

Il metodo delle mine potrebbe non essere il migliore in quanto le persone non amano il localizzatore di servizi per ottenere i componenti, è possibile utilizzarli come soluzione temporanea.

20

Le risposte di cui sopra mi portano a inline dipendenze e la funzione service override

Ecco il codice di registrazione:

container.Register(Component.For<IReport>().ImplementedBy<NortonService>().Named("nortonService")); 

container.Register(Component.For<ILogger>().ImplementedBy<FileLogger>()); 
container.Register(Component.For<ILogger>().ImplementedBy<DatabaseLogger>()); 

container.Register(
    Component.For<IReport>().ImplementedBy<McAfeeService>().Named("mcafeeService") 
     .DependsOn(Dependency.OnComponent<ILogger, DatabaseLogger>()) 
); 

IReport mcafeescan = container.Resolve<IReport>("mcafeeService"); 
mcafeescan.LogReport(); 

IReport nortonscan = container.Resolve<IReport>("nortonService"); 
nortonscan.LogReport(); 

uscita:

McAfee Scan has Logged data to a database 
Norton Scan has Logged data to a file 
9

Ho avuto un problema molto simile a questo, due implementazione di un'interfaccia e due implementazione di un'altra interfaccia. Volevo forzare l'utilizzo di particolari implementazioni di tali interfacce.

mia struttura di classe si presentava così -

enter image description here

ho guardato la convenzione di denominazione, ma non lo fece piace molto. Invece ho usato il seguente -

public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
    container.Register(
     Component.For<IMessageLoader>().ImplementedBy<MessageLoaderDatabase>() 
     ,Component.For<IMessageLoader>().ImplementedBy<MessageLoaderFile>() 

     ,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceDatabase>() 
      .DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderDatabase>()) 

     ,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceFile>() 
      .DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderFile>()) 

     ,Component.For<MessageOfTheDayController>().LifestyleTransient() 
      .DependsOn(Dependency.OnComponent<IMessageOfTheDayService, MessageOfTheDayServiceFile>()) 
    ); 

Le informazioni complete su questo approccio sono here. Nel codice sorgente fornito con quel post mostro altri due modi per ottenere lo stesso risultato.

2

Se si desidera eseguirlo in fase di esecuzione, è possibile ottenerlo tramite IHandlerSelector. Scrivi una classe che implementa IHandlerSelector. Fornisce un metodo SelectHandler che consente di definire la condizione per l'associazione condizionale in fase di esecuzione. Un gestore in questo caso è un componente di Windsor che partecipa ad esempio alla costruzione. Per ulteriori dettagli, consultare here.