Если вы не знаете, о чем я говорю, пройдите через учебник и попробуйте добавить зависимую инъекцию самостоятельно или попробуйте свою удачу с моим объяснением проблемы.
Примечание.. Эта проблема не входит в рамки исходного руководства по ASP.NET. В учебном пособии только предполагается, что используемые шаблоны являются дружественными к инъекциям.
Проблема в основном состоит в том, что существует цикл зависимостей между контроллером, ModelStateWrapper и ContactManagerService.
- Конструктор ContactController принимает IContactManagerService.
- Конструктор ContactManagerService принимает IContactManagerRepository (не важно) и документ IValidationDictionary (который реализует ModelStateWrapper).
- Конструктор ModelStateWrapper принимает ModelStateDictionary (который является свойством "ModelState" на контроллере).
Итак, цикл зависимостей выглядит так: Controller > Service > ModelStateWrapper > Controller
Если вы попытаетесь добавить инъекцию зависимостей к этому, он потерпит неудачу. Поэтому мой вопрос: что мне с этим делать? Другие задали этот вопрос, но ответов мало, разные, и все они кажутся "хаки-иш".
Мое текущее решение заключается в том, чтобы удалить IModelStateWrapper из конструктора IService и добавить метод Initialize вместо этого:
public class ContactController : Controller
{
private readonly IContactService _contactService;
public ContactController(IContactService contactService)
{
_contactService = contactService;
contactService.Initialize(new ModelStateWrapper(ModelState));
}
//Class implementation...
}
public class ContactService : IContactService
{
private IValidationDictionary _validationDictionary;
private readonly IContactRepository _contactRepository;
public ContactService(IContactRepository contactRepository)
{
_contactRepository = contactRepository;
}
private void Initialize(IValidationDictionary validationDictionary)
{
if(validationDictionary == null)
throw new ArgumentNullException("validationDictionary");
_validationDictionary = validationDictionary;
}
//Class implementation...
}
public class ModelStateWrapper : IValidationDictionary
{
private readonly ModelStateDictionary _modelState;
public ModelStateWrapper(ModelStateDictionary modelState)
{
_modelState = modelState;
}
//Class implementation...
}
С помощью этой конструкции я могу настроить контейнер единства следующим образом:
public static void ConfigureUnityContainer()
{
IUnityContainer container = new UnityContainer();
// Registrations
container.RegisterTypeInHttpRequestLifetime<IContactRepository, EntityContactRepository>();
container.RegisterTypeInHttpRequestLifetime<IContactService, ContactService>();
ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container));
}
К сожалению, это означает, что метод "Инициализировать" в службе должен вызываться вручную с помощью конструктора контроллера. Есть ли способ лучше? Может быть, где-то я включаю IValidationDictionary в мою конфигурацию единства? Должен ли я переключиться на другой контейнер DI? Я что-то пропустил?