2014-05-11 16 views
12

Tôi chỉ cố gắng tìm hiểu về PostSharp và thành thật mà nói tôi nghĩ nó thật tuyệt vời.PostSharp thay thế

Nhưng có một điều rất khó đối với tôi về cách thức tiêm phụ thuộc thuần túy (không phải định vị dịch vụ) cannot be done trong các khía cạnh PostSharp, có lẽ trong sự hiểu biết của tôi là kết quả của quá trình biên dịch thời gian.

Đến từ nền PHP, Symfony có JMSAopBundle vẫn cho phép phụ thuộc được tiêm vào Bộ chặn của nó.

.Net có một số thư viện có cùng khả năng không?

Hoặc tôi có thiếu gì đó với PostSharp không?

+3

Nếu bạn đã quan tâm đến việc thuần túy Dependency Injection, PostSharp là hoàn toàn dư thừa. Thay vào đó, bạn có thể chọn một DI Container hỗ trợ Interception thời gian chạy: http: // stackoverflow.com/a/7906547/126014 –

+1

Và sẽ đi xa hơn nữa bằng cách nói rằng việc chặn thời gian chạy là không cần thiết. – Steven

+0

@Steven Tôi nghĩ rằng nó linh hoạt hơn là dư thừa. Biên dịch đánh chặn thời gian sẽ không chờ đợi bất kỳ khởi tạo thời gian chạy nào của bất kỳ thứ gì. –

Trả lời

15

Tôi không nghĩ rằng bạn đang thiếu bất cứ điều gì ở đây và giới hạn thực sự là kết quả của việc sử dụng thời gian biên dịch dệt.

Mặc dù tôi nghĩ công cụ dệt thời gian biên dịch có vị trí trong phát triển phần mềm, tôi cảm thấy rằng chúng thường bị lạm dụng. Thường thì tôi thấy chúng được sử dụng để vá lỗi trong thiết kế ứng dụng. Trong các ứng dụng tôi xây dựng, tôi áp dụng các giao diện chung cho các khái niệm kiến ​​trúc nhất định. Ví dụ: tôi xác định:

  • Giao diện ICommandHandler<TCommand> cho các dịch vụ triển khai một trường hợp sử dụng nhất định;
  • giao diện IQueryHandler<TQuery, TResult> cho các dịch vụ thực hiện truy vấn;
  • giao diện IRepository<TEntity> là trừu tượng hóa trên các kho lưu trữ;
  • giao diện IValidator<TCommand> cho các thành phần thực thi xác thực thư;
  • v.v. v.v.

Điều này cho phép tôi tạo một trang trí chung chung cho các nhóm hiện vật đó (ví dụ: TransactionCommandHandlerDecorator<TCommand> cho phép chạy từng trường hợp sử dụng trong giao dịch của chính nó). Việc sử dụng trang trí có nhiều lợi thế, chẳng hạn như:

  • Những trang trí chung này hoàn toàn không công cụ, vì không có tham chiếu đến công cụ dệt mã hoặc khung chặn. Các khía cạnh PostSharp hoàn toàn phụ thuộc vào PostSharp và các trình chặn luôn luôn phụ thuộc vào một khung làm việc chặn, chẳng hạn như Castle.Proxy.
  • Vì một người trang trí chỉ là một thành phần bình thường, phụ thuộc có thể được tiêm vào hàm tạo và chúng có thể đóng vai trò bình thường khi bạn soạn đồ thị đối tượng bằng cách sử dụng Dependency Injection.
  • Mã trang trí rất sạch sẽ, vì thiếu sự phụ thuộc với bất kỳ công cụ của bên thứ ba nào.
  • Vì chúng là công cụ bất khả tri và cho phép tiêm phụ thuộc, trang trí có thể được kiểm tra đơn vị dễ dàng mà không cần phải hoàn nguyên về các thủ thuật đặc biệt.
  • Mã ứng dụng cần các mối quan tâm cắt ngang được áp dụng cũng có thể được thử nghiệm dễ dàng một cách đơn độc, bởi vì trang trí không được dệt trong thời gian biên dịch. Khi trang trí được dệt vào thời gian biên dịch, bạn luôn bị buộc phải thực hiện một kiểu tích hợp thử nghiệm mã ứng dụng của bạn hoặc cần hoàn nguyên các thủ thuật xây dựng đặc biệt để ngăn chúng không được áp dụng trong dự án thử nghiệm đơn vị của bạn.
  • Trang trí có thể được áp dụng động và có điều kiện khi chạy, vì không có quá trình biên dịch mã thời gian diễn ra.
  • Hiệu suất giống hệt nhau (hoặc thậm chí nhanh hơn) so với mã dệt, vì không có sự phản chiếu xảy ra trong khi xây dựng đối tượng.
  • Không cần đánh dấu các thành phần của bạn bằng các thuộc tính để lưu ý rằng một số khía cạnh phải được áp dụng. Điều này giúp mã ứng dụng của bạn không có bất kỳ kiến ​​thức nào về mối quan tâm xuyên suốt và làm cho việc thay thế này trở nên dễ dàng hơn nhiều. (lưu ý rằng bạn có thể sử dụng cách tiếp cận thuộc tính-less này với PostSharp, nhưng bạn cần phiên bản thương mại để kéo nó ra).

Rất nhiều đã được viết về loại thiết kế ứng dụng này; đây là một vài điều tôi đã viết bản thân mình:

CẬP NHẬT

trang trí là rất lớn, nhưng những gì tôi thích về AOP là đó là khái niệm về lời khuyên và điểm tham gia. Có cách nào để mô phỏng cùng khả năng với trang trí không? Tôi chỉ có thể nghĩ về sự phản chiếu ngay bây giờ.

A Tham gia điểm là "vị trí được xác định rõ ràng trong lớp học sẽ được đính kèm". Khi bạn áp dụng AOP bằng cách sử dụng trang trí, bạn sẽ bị 'giới hạn' để tham gia các điểm nằm trên ranh giới phương thức. Tuy nhiên, nếu bạn tuân thủ SRP, OCPISP, bạn sẽ có giao diện rất mỏng (thường là với một phương pháp duy nhất). Khi làm điều đó, bạn sẽ nhận thấy rằng không bao giờ có một lý do để có một điểm tham gia tại bất kỳ nơi nào khác trong lớp học của bạn.

An Lời khuyên là "mối quan tâm có khả năng sẽ thay đổi đầu vào và/hoặc đầu ra của phương pháp được nhắm mục tiêu". Khi làm việc với trang trí và thiết kế dựa trên thông điệp (điều tôi đang quảng bá ở đây), lời khuyên của bạn cần thay đổi thông điệp (hoặc thay thế thông điệp hoàn chỉnh bằng giá trị thay đổi) hoặc thay đổi giá trị đầu ra. Mọi thứ không khác nhiều so với việc viết mã, vì nếu bạn áp dụng Lời khuyên, phải có một điểm chung giữa tất cả các mã mà Tư vấn được áp dụng. Vì tôi thực sự thích hỗ trợ biên dịch thời gian, tôi thường xác định tính phổ biến này với các giao diện. Điều này cho phép tôi viết một trang trí với một ràng buộc kiểu chung cho giao diện cụ thể đó, có nghĩa là trang trí chỉ có thể được áp dụng ở đó. Ví dụ:

public class AddUserContextCommandHandlerDecorator<TCommand> 
    : ICommandHandler<TCommand> 
    where TCommand : IUserContextCommand 
{ 
    private readonly ICommandHandler<TCommand> decoratee; 
    private readonly IUserContext userContext; 

    public AddUserContextCommandHandlerDecorator(
     ICommandHandler<TCommand> decoratee, 
     IUserContext userContext) { 
     this.decoratee = decoratee; 
     this.userContext = userContext; 
    } 

    public void Handle(TCommand command) { 
     command.UserId = this.userContext.UserId; 
     command.UserRoles = this.userContext.UserRoles; 

     this.decoratee.Handle(command); 
    } 
} 

Ở đây AddUserContextCommandHandlerDecorator có thể được áp dụng cho tất cả các ICommandHandler<TCommand> triển khai nơi TCommand thực hiện IUserContextCommand. IUserContextCommand chứa các thuộc tính UserIdUserRoles. Ở đây bạn thấy rằng người trang trí thay đổi thông báo command trước khi gửi đến decoratee của nó. Do lưu ý rằng IMO trong trường hợp này nó sẽ thường là tốt hơn để tiêm IUserContext vào trình xử lý lệnh thực, thay vì truyền thông tin theo ngữ cảnh này bằng thông báo.

+0

blog tuyệt vời, nhưng tôi có một câu hỏi mặc dù. Trang trí rất tuyệt, nhưng điều tôi thích về AOP là khái niệm tư vấn và tham gia các điểm. Có cách nào để mô phỏng khả năng tương tự với trang trí? Tôi chỉ có thể nghĩ về sự phản chiếu ngay bây giờ. –

+0

@SamuelAdam: Xem cập nhật của tôi. – Steven

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