2009-11-30 2 views
5

У меня есть обертка на ModelStateDictionary, которую все мои службы принимают. Можно ли настроить autofac для вставки контроллера ModelStateDictionary в конструктор оболочки и затем ввести его в конструктор службы?Как передать модель ModelState контроллера моему сервисному конструктору с помощью Autofac?

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

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

Благодаря

+0

Просто обновил свой ответ с возможно интересной идеей, которая спасет вас от объявления кучи заводских делегатов. –

ответ

8

на основе ваших комментариев Настоящим я пересматриваю свой ответ :)

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.

+0

Контейнер создает новый ModelStateDictionary и передает его конструктору ModelValidation. Я хотел бы передать существующий ModelStateDictionary (который доступен через свойство Controller.ModelState) в конструктор ModelValidation. Является ли это возможным? – Valentin

+0

Не могли бы вы рассказать об этом в своем вопросе? является Controller.ModelState статичным? или как это объявлено сегодня? –

+0

Элемент Controller.ModelState является свойством ModelStateDictionary. Контроллер создается с помощью asp.net mvc runtime (фабрика контроллера), и там создается ModelStateDictionary. Затем я могу создать свои контроллеры путем подклассификации контроллера, и я могу получить доступ к свойству ModelState в своем классе. Если я неясен, сообщите мне, и я подробно расскажу о своем вопросе. – Valentin

0

Добавить новый конструктор без проверки. Назначьте службу ValidationService с помощью свойства.

Имущества должен быть реализован в интерфейсе 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

Можете ли вы добавить как один экземпляр – Farid

+0

Этот вопрос уже давно не актуальен, извините. Я даже не программирую .NET больше :) – Valentin

Смежные вопросы