на основе ваших комментариев Настоящим я пересматриваю свой ответ :)
ModelStateDictionary
явно не службы, которая должна быть решена с помощью контейнера, а скорее данные что РЕКОМЕНДУЕМОГО предоставляться во время создания экземпляра. Мы можем сказать, что из-за того, что ModelState принадлежит каждому экземпляру Controller и, таким образом, недоступен для контейнера в «время разрешения».
Кроме того, каждый экземпляр ModelValidation
будет связан с ModelStateDictionary
, например, и, таким образом, также следует рассматривать как данных.
В Autofac, когда данные должны быть переданы конструкторам (необязательно в дополнение к другим зависимостям), мы должны использовать делегаты фабрики. Эти делегаты будут обрабатывать зависимость и передачу данных конструктору. Сладкая вещь с Autofac заключается в том, что эти делегаты могут быть автогенерированы.
Я предлагаю следующее решение:
Так как ModelValidation и CustomerService требуют данных в своих конструкторах, нам нужны два завода делегатов (примечание: имена параметров должны совпадать с именами в соответствующих их конструктору):
public delegate IModelValidation ModelValidationFactory(ModelStateDictionary msd);
public delegate CustomerService CustomerServiceFactory(ModelStateDictionary msd);
поскольку контроллеры не должен знать, куда приходит эти делегаты из них должны быть переданы в конструктор контроллера в качестве зависимостей:
public class EditCustomerController : Controller
{
private readonly CustomerService _customerService;
public EditCustomerController(CustomerServiceFactory customerServiceFactory
/*, ...any other dependencies required by the controller */
)
{
_customerService = customerServiceFactory(this.ModelState);
}
}
CustomerService должен иметь конструктор, похожее на это (возможно справиться с некоторыми из этого в классе ServiceBase):
public class CustomerService
{
private readonly IModelValidation _modelValidation;
public CustomerService(ModelStateDictionary msd,
ModelValidationFactory modelValidationFactory)
{
_modelValidation = modelValidationFactory(msd);
}
Для того, чтобы это произошло, мы должны построить наш контейнер, как это:
var builder = new ContainerBuilder();
builder.Register<ModelValidation>().As<IModelValidation>().FactoryScoped();
builder.Register<CustomerService>().FactoryScoped();
builder.RegisterGeneratedFactory<ModelValidationFactory>();
builder.RegisterGeneratedFactory<CustomerServiceFactory>();
builder.Register<EditCustomerController>().FactoryScoped();
Поэтому, когда контроллер решен (например, при использовании the MvcIntegration module), делегаты фабрики будут введены в контроллеры и службы.
Update: сократить требуемый код даже больше, вы могли бы заменить CustomerServiceFactory
с родовой фабрикой делегатом, как я описал here.
Просто обновил свой ответ с возможно интересной идеей, которая спасет вас от объявления кучи заводских делегатов. –