2013-06-18 35 views
5

Tôi sử dụng Lâu đài Windsor khá lâu rồi. Nó chỉ là hoàn hảo cho môi trường nơi dữ liệu được đặt trong một cơ sở dữ liệu hoặc tương tự, nơi mà mô hình kho lưu trữ hoặc mô hình unitofwork hoạt động tốt.Windsor Castle/DI và mô hình đối tượng

Bây giờ tôi có một tình huống khác: Tôi có một mô hình đối tượng phức tạp được lắp ráp bởi rất nhiều PONO đơn lẻ. Môi trường bị ảnh hưởng mạnh mẽ bởi COM, để làm cho nó rõ ràng hơn: Excel, Word PIOs được sử dụng nhiều.

Tôi sử dụng mẫu lệnh, tôi đã triển khai ICommandHandler như mô tả here nhưng có một sự khác biệt. Vì tôi muốn lắp ráp các lệnh vào một danh sách các lệnh để gọi chúng trong một lần chạy mà không biết bất cứ điều gì bên cạnh mẫu lệnh chung được mô tả, nó không đưa ra giới thiệu ngữ cảnh khi gọi phương thức thực thi. Giao diện trông giống như thế này:

public interface ICommand 
    { 
     void Execute(); 
     bool CanExecute(); 
    } 

Thực hiện các lệnh với giao diện đó có hiệu quả và dễ hiểu. Mặt khác, nó là một vấn đề để giới thiệu bối cảnh với ctor vì vì vậy Container phải được gọi một cách rõ ràng để ví dụ. thêm tham số ctor.

Vì vậy, tôi thực sự có hai câu hỏi:

  1. Có thể tiêm một - chúng ta hãy gọi nó là một bối cảnh, một phần của mô hình đối tượng - tự động bởi Windsor lâu đài mà không gọi container explictely?
  2. Cách tham gia từ mẫu lệnh bằng cách sử dụng DI? Bất kỳ ý tưởng làm thế nào để hoàn thành việc có thể xác định một danh sách các nhiệm vụ/hành động hoặc tương tự bằng cách làm theo quy tắc RRR được mô tả here?
+0

Bạn liên kết đến mô tả mẫu lệnh/trình xử lý (sử dụng 'ICommandHandler '), nhưng thực tế bạn đang sử dụng Mẫu lệnh, điều này hoàn toàn khác, vì các lệnh trong mẫu lệnh/trình xử lý là DTO không có hành vi, và chúng không chứa phương thức 'Execute'. Có một phương thức 'Execute' trên chúng sẽ vô hiệu hóa hầu hết các khả năng mà mẫu lệnh/handler mang lại. Các vấn đề với việc tiêm phụ thuộc vào các lệnh sẽ biến mất khi bạn đưa các phụ thuộc vào các trình xử lý. Trong mẫu lệnh/handler, các lệnh không có bất kỳ phụ thuộc nào (vì chúng không có bất kỳ hành vi nào). – Steven

+0

Cảm ơn câu trả lời, Steven. Bạn chắc chắn đúng, tôi có thể tiêm chúng vào bộ xử lý. Nhưng điều đó không giải quyết được vấn đề, do tôi vẫn phải tiêm cùng một thông tin và gọi vùng chứa để làm cho dữ liệu của tôi có sẵn cho trình xử lý. Nó sẽ không thể thực hiện các lệnh batch và thực hiện chúng trong một hàng. Tôi đã nhận được bất cứ điều gì sai? –

Trả lời

4

Cơ sở hạ tầng:

public interface ICommandHandler<in T> 
{ 
    void Handle(T command); 
} 

public interface ICommandExecutor 
{ 
    CommandResult ExecuteCommand(Command command); 
    CommandResult ExecuteCommands(Command[] commands); 
} 

public abstract class Command 
{ 

} 

public class CommandExecutor : ICommandExecutor 
{ 
    private readonly IWindsorContainer _kernel; 

    public CommandExecutor(IWindsorContainer kernel) 
    { 
     Guard.AssertNotNull(() => kernel); 
     _kernel = kernel; 
    } 

    public CommandResult ExecuteCommand(Command command) 
    { 
     return ExecuteInternal(command); 
    } 

    public CommandResult ExecuteCommands(Command[] commands) 
    { 
     CommandResult result = null; 

     foreach (Command command in commands) 
     { 
      result = ExecuteInternal(command); 

      if (!result.IsExecuted) 
       return result; 
     } 

     return result ?? CommandResult.Executed("Command executed successfully"); 
    } 

    private CommandResult ExecuteInternal(Command command) 
    { 
     dynamic handler = FindHandlerForCommand(command); 

     try 
     { 
      handler.Handle(command as dynamic); 
      return CommandResult.Executed("Command executed successfully"); 
     } 
     finally 
     { 
      _kernel.Release(handler); 
     } 
    } 

    private object FindHandlerForCommand(Command command) 
    { 
     Type handlerType = typeof (ICommandHandler<>).MakeGenericType(command.GetType()); 
     dynamic handler = _kernel.Resolve(handlerType); 
     return handler; 
    } 
} 

đăng ký:

 container.Register(Component.For<ICommandExecutor>().ImplementedBy<CommandExecutor>() 
      .Interceptors<ExceptionToCommandResult>() 
      .Interceptors<ExceptionLogger>() 
      .Interceptors<HandleWhenDeadlockVictim>() 
      .Interceptors<RetryCommand>() 
      .Interceptors<ContainerScopeWrapper>() 
      .Interceptors<TransactionWrapper>() 
      .Interceptors<SameNhibernateSessionAndTransactionWrapper>()); 

Ví dụ:

public class WriteComment : Command 
{ 
    public string GameToCommentId { get; set; } 

    public string Comment { get; set; } 
} 

public class WriteCommentCommandHandler : ICommandHandler<WriteComment> 
{ 
    private readonly IGameRepository _repository; 

    public WriteCommentCommandHandler(IGameRepository repository) 
    { 
     Guard.AssertNotNull(() => repository); 
     _repository = repository; 
    } 

    public void Handle(WriteComment command) 
    { 
     var game = _repository.Get(new Guid(command.GameToCommentId)); 

     game.WriteComment(command.Comment, DateTime.Now); 
    } 
} 

Tất cả những thứ AOP xử lý giao dịch và vân vân. Người thực thi lệnh là một singleton không quốc tịch, các trình xử lý chỉ định các nhu cầu khác nhau của chúng. Trình thực thi lệnh chỉ là cơ sở hạ tầng và khả năng bất khả tri miền, do đó, hãy đặt nó ở nơi bạn thích bên ngoài miền của mình. Đây là mã sản xuất trên một hệ thống lớn, hoạt động như một sự quyến rũ.

+0

Marius, cảm ơn rất nhiều. Khá toàn diện. Sẽ thử nó! –

Các vấn đề liên quan