2009-11-30 19 views
5

Tôi có một wrapper trên ModelStateDictionary mà tất cả các dịch vụ của tôi chấp nhận. Có thể cấu hình autofac để tiêm bộ điều khiển ModelStateDictionary vào hàm khởi tạo của trình bao bọc và sau đó tiêm nó vào bộ dựng dịch vụ không?Làm thế nào để vượt qua ModelState của bộ điều khiển cho nhà xây dựng dịch vụ của tôi với Autofac?

//code 
public class ModelValidation : IModelValidation { 
public ModelValidation(ModelStateDictionary msd){...} 
.. 
.. 
} 

public class CustomerService{ 
public CustomerService(IModelValidation mv){...} 
.. 
} 

Cảm ơn

+0

Chỉ cần cập nhật câu trả lời của tôi với một ý tưởng có thể là thú vị mà sẽ giúp bạn tiết kiệm từ tuyên bố một loạt các đại biểu nhà máy. –

Trả lời

8

Dựa trên ý kiến ​​của bạn tôi xin sửa lại câu trả lời của tôi :)

ModelStateDictionary rõ ràng không phải là một dịch vụ cần được giải quyết bằng container, mà đúng hơn là dữ liệu rằng nên được cung cấp tại thời điểm khởi tạo. Chúng ta có thể nói rằng từ thực tế là ModelState được sở hữu bởi mỗi cá thể Controller và do đó không có sẵn cho container tại "thời gian giải quyết".

Hơn nữa, mỗi trường hợp ModelValidation sẽ bị ràng buộc vào trường hợp ModelStateDictionary và do đó cũng được coi là dữ liệu.

Trong Autofac, khi dữ liệu phải được truyền cho các nhà xây dựng (tùy chọn ngoài các phụ thuộc khác), chúng tôi phải sử dụng các đại biểu của nhà máy. Các đại biểu này sẽ xử lý sự phụ thuộc và dữ liệu truyền vào hàm tạo. Điều ngọt ngào với Autofac là các đại biểu này có thể được tự động phát hiện.

Tôi đề nghị các giải pháp sau đây:

Kể từ khi cả hai ModelValidation và hậu mãi đòi hỏi dữ liệu trong nhà thầu của họ, chúng ta cần hai đại biểu nhà máy (lưu ý: tên tham số phải khớp với tên trong constructor tương ứng của họ):

public delegate IModelValidation ModelValidationFactory(ModelStateDictionary msd); 
public delegate CustomerService CustomerServiceFactory(ModelStateDictionary msd); 

Kể từ bộ điều khiển của bạn không nên biết được nơi các đại biểu đến từ họ nên được chuyển tới các nhà xây dựng bộ điều khiển như phụ thuộc:

public class EditCustomerController : Controller 
{ 
    private readonly CustomerService _customerService; 

    public EditCustomerController(CustomerServiceFactory customerServiceFactory 
     /*, ...any other dependencies required by the controller */ 
     ) 
    { 
     _customerService = customerServiceFactory(this.ModelState); 
    } 

} 

Các hậu mãi nên có một constructor tương tự như sau (tùy chọn xử lý một số điều này trong một lớp học ServiceBase):

public class CustomerService 
{ 
    private readonly IModelValidation _modelValidation; 

    public CustomerService(ModelStateDictionary msd, 
       ModelValidationFactory modelValidationFactory) 
    { 
     _modelValidation = modelValidationFactory(msd); 
    } 

Để thực hiện điều này chúng ta cần phải xây dựng container của chúng tôi như thế này:

var builder = new ContainerBuilder(); 

builder.Register<ModelValidation>().As<IModelValidation>().FactoryScoped(); 
builder.Register<CustomerService>().FactoryScoped(); 

builder.RegisterGeneratedFactory<ModelValidationFactory>(); 
builder.RegisterGeneratedFactory<CustomerServiceFactory>(); 

builder.Register<EditCustomerController>().FactoryScoped(); 

Vì vậy, khi bộ điều khiển được giải quyết (ví dụ: khi sử dụng the MvcIntegration module), các đại biểu của nhà máy sẽ được đưa vào bộ điều khiển và dịch vụ.

Cập nhật: để cắt giảm mã yêu cầu nhiều hơn, bạn có thể thay thế CustomerServiceFactory bằng đại diện nhà máy chung như tôi đã mô tả here.

+0

Vùng chứa tạo ra ModelStateDictionary mới và chuyển nó tới hàm tạo ModelValidation. Tôi muốn vượt qua ModelStateDictionary hiện tại (có thể truy cập thông qua thuộc tính Controller.ModelState) đến constructor ModelValidation. Có thể không? – Valentin

+0

Bạn có thể giải thích điều này trong câu hỏi của mình không? Controller.ModelState là tĩnh? hoặc ngày nay nó được tuyên bố như thế nào? –

+0

Controller.ModelState là thuộc tính của kiểu ModelStateDictionary. Bộ điều khiển được tạo ra bởi thời gian chạy asp.net mvc (nhà máy điều khiển), và ModelStateDictionary được tạo ra ở đó. Sau đó, tôi có thể tạo các bộ điều khiển bằng cách phân lớp bộ điều khiển và tôi có thể truy cập thuộc tính ModelState trong lớp của mình. Nếu tôi không rõ ràng, vui lòng cho tôi biết và tôi sẽ trả lời chi tiết hơn về câu hỏi của tôi. – Valentin

0

Thêm hàm tạo mới mà không có ValidationService. Chỉ định ValidationService bằng cách sử dụng một thuộc tính.

Tài sản phải được thực hiện trong giao diện ICostumerService

public class ModelStateWrapper: IValidationDictionary { 
public ModelStateWrapper(ModelStateDictionary msd){} 
} 

public class CustomerService: ICostumerService{ 
public IValidationDictionary ValidationDictionary { get; set; } 
public CustomerService(ICustomerRepsitory customerRepository, IValidationDictionary validationDictionary){} 
public CustomerService(ICustomerRepsitory customerRepository){} 
} 

public Controller(ICustomerService customerService) 
{ 
    _customerService= menuService; 
    _customerService.ValidationDictionary = new ModelStateWrapper(this.ModelState); 
    _customerService= sportsService; 
} 
1
Builder.RegisterInstance(new ModelStateDictionary()).SingleInstance(); 
      builder.Register(c => new SW.PL.Util.ModelStateWrapper 
(c.Resolve<ModelStateDictionary>())).As<IValidationDictionary>().InstancePerHttpRequest(); 
+0

Bạn có thể thêm làm ví dụ đơn lẻ – Farid

+0

Câu hỏi này là một thời gian dài không còn thực tế, xin lỗi. Tôi thậm chí không lập trình .NET nữa :) – Valentin

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