2011-08-26 52 views
21

Tôi có một bộ điều khiển cơ bản trừu tượng có một hàm tạo mà tôi hy vọng sẽ được điền bởi autofac khi các bộ điều khiển được xây dựng.Constructor tiêm vào một lớp cơ sở sử dụng autofac

public abstract class BaseController : Controller 
{ 
    protected ILogger { get; private set; } 

    protected BaseController() 
    { 
    } 

    protected BaseController(ILogger logger) 
    { 
     Logger = logger; 
    } 
} 

Điều này dường như không hoạt động khi tôi lấy được bộ điều khiển từ nó.

Tôi chỉ có thể làm việc này khi tôi gọi hàm khởi tạo một cách rõ ràng từ bộ điều khiển. Đây có phải là cách đúng để thực hiện việc này không?

public class PublicController : BaseController 
{ 
    public PublicController() 
    { 
    } 

    public PublicController(ILogger logger) : base(logger) 
    { 

    } 
} 

Ngoài ra, bằng cách sử dụng hội nhập tích hợp mvc, dường như không có cách nào để chia sẻ vùng chứa cho các lớp khác để tự giải quyết. Tôi đọc ở đâu đó rằng điều này không được khuyến khích, tại sao không? Đây có phải chỉ để tách rời sự phụ thuộc của bất kỳ khung ioc đơn nào không? Là người xây dựng tiêm chỉ chỉ cách để áp dụng các phụ thuộc xuống the heirachy.

Cảm ơn

Trả lời

48

Gọi hàm tạo lớp cơ sở một cách rõ ràng là cách duy nhất để thực hiện việc này bằng cách sử dụng phép dựng hàm dựng trong C#. Có vẻ như bạn nên loại bỏ các nhà xây dựng không có tham số từ BaseControllerPublicController vì chúng không bao giờ thực sự được gọi khi có trình ghi nhật ký.

Vấn đề tiêm phụ thuộc vào bộ điều khiển cơ sở là vấn đề phổ biến khi sử dụng ASP.NET MVC và IoC. Có nhiều lựa chọn/trường phái tư tưởng.

1.) Sử dụng dịch vụ tổng hợp. Để duy trì các hàm tạo lớp dẫn xuất đơn giản, hãy tạo một dịch vụ đơn lẻ hiển thị hoặc ủy quyền cho tất cả các dịch vụ khác nhau cần thiết bởi bộ điều khiển cơ sở (ví dụ: IBaseControllerDependencies hoặc tương tự.) Sau đó chuyển dịch vụ này tới BaseController giống như bạn đang làm với ILogger tại đây.

Có nhiều ưu điểm khác nhau tùy thuộc vào ứng dụng của bạn và số lượng lớp cơ sở bạn đang sử dụng.Google cho 'dịch vụ tổng hợp Autofac' để xem thêm về điều này.

2.) Sử dụng tính năng tiêm thuộc tính. Tận dụng tối ILogger tài sản trên public class cơ sở của bạn, và cấu hình chai lọ bằng:

builder.RegisterControllers().PropertiesAutowired(); 

tiêm tài sản là không thực sự là một kỹ thuật được ưa chuộng trong Autofac. Vai trò của nhà xây dựng để chấp nhận các phụ thuộc, trong khi các thuộc tính có thể ghi được thường được xem như là một mùi mã, vì vậy Autofac không thực sự tối ưu hóa cho trường hợp này. Một trong những hạn chế là các thuộc tính có thể ghi được rằng không nên được tiêm thường là nhầm lẫn, với những hậu quả kỳ lạ.

3.) Chức năng điều khiển cơ sở Refactor thành nhiều bộ lọc hành động khác nhau. Autofac có thể đưa các bộ lọc hành động vào đường dẫn gọi hành động MVC. Do đó, các bộ lọc có thể lấy các phụ thuộc nằm trong lớp cơ sở và các mối quan tâm tương tự có thể được áp dụng theo cách cắt ngang. Thông tin thêm về điều này trên web, ExtensibleActionInvoker.InjectActionInvoker() trỏ đến thông tin bạn cần. Không phải luôn luôn có thể với tất cả các mối quan tâm.

4, cũng là câu trả lời cho câu hỏi thứ hai của bạn.) Giải quyết các phụ thuộc bộ điều khiển cơ sở sử dụng vị trí dịch vụ từ DependencyResolver.Current.

var logger = DependencyResolver.Current.GetService<ILogger>(); 

Lý do không được khuyến khích là nó làm cho ứng dụng kết quả khó hiểu hơn vì không còn khả năng xem dịch vụ phụ thuộc vào thành phần nào. những gì phải được cấu hình trong container trước khi một thành phần cụ thể có thể được sử dụng, người ta phải xem xét toàn bộ codebase của thành phần để tìm các cuộc gọi GetService(). Một trở ngại đáng chú ý khi thử nghiệm đơn vị.

Hy vọng điều này sẽ giúp ích cho bạn, một chút về kết xuất não tôi biết :) Những người khác có thể thêm một số ý tưởng vào những thứ này.

2

Tôi không có quyền bình luận để yêu cầu chi tiết hơn, nhưng tôi cần phải nhìn thấy mã số đăng ký của bạn để hiểu những gì bạn mong đợi và lý do tại sao container không đáp ứng được những mong đợi.

Đối với các câu hỏi bổ sung của bạn: không nhất thiết phải là cách để lớp tự giải quyết, nhưng một lớp có thể phụ thuộc vào nhà máy đối tượng có thể phân giải tự động cho loại đã biết (thường là đủ). Nếu bạn đã đăng ký A, bạn có thể phụ thuộc vào Func<A>. Có nhiều loại quan hệ như thế này trong Autofac; xem http://code.google.com/p/autofac/wiki/RelationshipTypes.

"Chia sẻ vùng chứa" không được khuyến khích vì nó có xu hướng ẩn phụ thuộc của lớp. Nếu một phụ thuộc vào container được thực hiện, hoặc được tham chiếu như một đối tượng "IoC" toàn cục, thì sự biểu hiện của các phụ thuộc cụ thể bị mất.

Giải quyết các phụ thuộc trong hệ thống phân cấp không phải là vấn đề, vì bạn đã sử dụng tính năng tiêm c'tor, tôi không chắc vấn đề của bạn là gì. Có những mối quan tâm phụ trợ, chẳng hạn như sửa đổi tất cả các lớp con của bạn nếu các phụ thuộc lớp cơ sở của bạn thay đổi. May mắn thay, Autofac có một câu trả lời cho rằng trong dịch vụ tổng hợp (http://code.google.com/p/autofac/wiki/AggregateService).

Autofac là một công cụ tuyệt vời, sâu sắc. Một gợi ý nữa, nếu bạn chỉ mới bắt đầu, hãy dành một chút thời gian để quấn đầu của bạn xung quanh tuổi thọ đối tượng và phạm vi cuộc đời (đặc biệt là http://nblumhardt.com/2011/01/an-autofac-lifetime-primer/). Chúc may mắn!

0

Autofac cho .NET Lõi

Install

PM> Install-Package Autofac.Core.NonPublicProperty 

Sử dụng

builder.RegisterType<AppService>() 
    .AsImplementedInterfaces() 
    .AutoWireNonPublicProperties(); 
Các vấn đề liên quan