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.
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. –