Czy istnieje dobry / właściwy sposób rozwiązania problemu pętli wtrysku zależności w samouczku menedżera kontaktów ASP.NET MVC?

Jeśli nie wiesz, o czym mówię, albo przejdźsamouczek i spróbuj dodać zastrzyk zależności samodzielnie lub spróbuj szczęścia z moim wyjaśnieniem problemu.

Uwaga: Ten problem nie wchodzi w zakres oryginalnego samouczka ASP.NET. Samouczek sugeruje, że używane wzory są przyjazne dla wtrysku zależności.

Problem polega zasadniczo na tym, że istnieje pętla zależności między kontrolerem, ModelStateWrapper i ContactManagerService.

Element sterujący ContactController pobiera usługę IContactManagerService.Konstruktor ContactManagerService pobiera repozytorium IContactManagerRepository(nieważne) i IValidationDictionary(które implementuje ModelStateWrapper).Konstruktor ModelStateWrapper przyjmuje ModelStateDictionary(która jest właściwością o nazwie „ModelState” na kontrolerze).

Tak więc cykl zależności wygląda następująco: Controller> Service> ModelStateWrapper> Controller

Jeśli spróbujesz dodać zastrzyk zależności do tego, nie powiedzie się. Więc moje pytanie jest; co powinienem z tym zrobić? Inni opublikowali to pytanie, ale odpowiedzi są nieliczne, różne i wszystkie wydają się „hack-ish”.

Moim obecnym rozwiązaniem jest usunięcie IModelStateWrapper z konstruktora IService i dodanie metody Initialize zamiast tego:

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

Dzięki tej konstrukcji mogę skonfigurować mój kontener jedności w ten sposób:

public static void ConfigureUnityContainer()
{
    IUnityContainer container = new UnityContainer();

    // Registrations
    container.RegisterTypeInHttpRequestLifetime<IContactRepository, EntityContactRepository>();
    container.RegisterTypeInHttpRequestLifetime<IContactService, ContactService>();

    ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container));
}

Niestety oznacza to, że należy wywołać metodę „Inicjalizuj” w usłudzeręcznie przez konstruktora kontrolera. Czy jest lepszy sposób? Może gdzieś w jakiś sposób włączam IValidationDictionary do mojej konfiguracji jedności? Czy powinienem przełączyć się na inny kontener DI? Czy czegoś mi brakuje?

questionAnswers(3)

yourAnswerToTheQuestion