StructureMap считает, что он должен внедрить конструктор и выдает исключение

Я использую StructureMap и ASP.Net Identity в своем приложении. Когда у меня есть эта строка в моем Application_Start

ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());

а это StructureMapControllerFactory:

public class StructureMapControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null && requestContext.HttpContext.Request.Url != null)
            throw new InvalidOperationException(string.Format("Page not found: {0}",
                requestContext.HttpContext.Request.Url.AbsoluteUri.ToString(CultureInfo.InvariantCulture)));
        return ObjectFactory.GetInstance(controllerType) as Controller;
    }
}

return ObjectFactory.GetInstance(controllerType) as Controller; бросает StructureMapConfigurationException исключение говорит:

No default Instance is registered and cannot be automatically determined for type 'IUserStore<Person>'

но если я уберу ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory()); Строка все идет хорошо, так что это проблема StructureMap, а не мой код.

1 ответ

Решение

Я думаю, что исключение очевидно. Вероятно, речь идет об AccountController из шаблона Identity, который поставляется с двумя конструкторами.

StructureMap будет использовать самый жадный конструктор по умолчанию. Шаблон поставляется с 2 конструкторами, один конструктор по умолчанию и один конструктор с ApplicationUserManager объект.

Без StructureMap вызывается конструктор по умолчанию, и ApplicationUserManager будет разрешен с использованием антишаблона локатора службы.

StructureMap теперь должен создать ApplicationUserManager и потому что это конкретный тип, он попробует. Если это был абстракция, то тут же возникнет исключение. ApplicationUserManager Однако есть один конструктор, который нуждается в IUserStore<Person>, Поскольку это абстракция и контейнер не имеет регистрации этого типа, StructureMap не может создать тип для вас.

Чтобы решить эту проблему, вы должны удалить конструктор по умолчанию и зарегистрировать ApplicationUserManager и зависящие от него сервисы, которые являются, по крайней мере, некоторым компонентом, реализующим IUserStore.

Изменить: Хотя решение, которое вы упомянули в комментариях, может работать, это не является предпочтительным решением из-за:

  1. Наличие нескольких конструкторов является анти-паттерном
  2. Теперь вы используете анти-шаблон сервисного локатора для разрешения ApplicationUserManager от HttpContext

Шаблоны, поставляемые с VS2013, нуждаются в некоторой работе для использования с внедрением зависимостей. Это будет стоить времени. Хорошей новостью является то, что это возможно и выполнимо и значительно улучшит ваши знания Owin, Asp.Net Identity, Внедрение зависимостей и ТВЕРДЫЙ дизайн.

Есть несколько блогов о том, как начать рефакторинг шаблонов для работы с внедрением зависимостей. Вы можете прочитать об этом здесь и здесь

Другие вопросы по тегам