2013-08-02 26 views
19

Khi đăng ký thành phần trong Castle Windsor, làm cách nào để chúng tôi ràng buộc việc triển khai cụ thể giao diện cho một thành phần có phụ thuộc vào giao diện đó. Tôi biết trước việc triển khai nào cần được sử dụng bởi thành phần.Castle Windsor - thực hiện nhiều giao diện

Ví dụ: tôi đã tạo một ứng dụng bảng điều khiển mẫu dựa trên mã từ một số blog và hướng dẫn.

Sau đây là mã.

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(); 
    } 
} 

Tôi muốn NortonService luôn sử dụng Filelogger và McAfeeService để sử dụng Trình ghi cơ sở dữ liệu.

Trong chương trình trên, tôi không thể liên kết NortonService với FileLogger.

Cách thực hiện?

Trả lời

2

câu trả lời của tôi có lẽ không phải là tốt nhất, bạn có thể sử dụng phương pháp đặt tên để giải quyết thực hiện đa:

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

Trong chức năng của bạn gọi điện thoại, bạn cần phải giải quyết nó theo tên: -

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

Phương pháp mỏ có lẽ không phải là phương pháp tốt nhất vì mọi người không thích định vị dịch vụ để lấy các thành phần, bạn có thể sử dụng nó như là giải pháp tạm thời.

20

Những câu trả lời ở trên đưa tôi đến với nội tuyến phụ thuộc và tính năng service override

Đây là mã đăng ký:

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(); 

Output:

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

Tôi đã có một vấn đề rất như thế này, hai triển khai thực hiện một giao diện và hai giao diện thực hiện khác. Tôi muốn ép buộc sử dụng các triển khai cụ thể của các giao diện đó.

cấu trúc lớp của tôi trông như thế này -

enter image description here

tôi nhìn vào quy ước đặt tên, nhưng không thực sự thích nó. Thay vào đó, tôi đã sử dụng các mục sau -

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>()) 
    ); 

Thông tin đầy đủ về phương pháp này là here. Trong mã nguồn được cung cấp cùng với bài viết đó, tôi trình bày hai cách khác để đạt được kết quả tương tự.

2

Nếu bạn muốn làm điều đó trong thời gian chạy, Điều này có thể đạt được thông qua IHandlerSelector. Viết một lớp thực hiện IHandlerSelector. Nó cung cấp một phương thức SelectHandler, nó sẽ cho phép bạn xác định điều kiện cho ràng buộc có điều kiện khi chạy. Một Handler trong trường hợp này là một thành phần trong Windsor tham gia vào việc xây dựng thể hiện. Tham khảo here để biết thêm chi tiết.