StructureMap 认为它必须注入构造函数并抛出异常
StructureMap thinks it has to inject to constructor and throws exception
我在我的应用程序中使用 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 的问题,而不是我的代码。
我认为例外很明显。这可能是关于身份模板中的 AccountController,它带有 2 个构造函数。
StructureMap 默认使用 most greediest constructor。该模板带有 2 个构造函数,一个默认构造函数和一个带有 ApplicationUserManager
对象的构造函数。
如果没有 StructureMap,将调用默认构造函数,并且将使用 service locator anti pattern.
解析 ApplicationUserManager
StructureMap 现在必须创建 ApplicationUserManager
,因为这是一个具体类型,所以它会尝试。如果它是一个抽象的,它会在那里抛出异常。然而,ApplicationUserManager
有一个需要 IUserStore<Person>
的构造函数。因为这是一个抽象并且容器没有注册这种类型,所以 StructureMap 无法为您创建类型。
要解决此问题,您应该删除默认构造函数并注册 ApplicationUserManager 和相关服务,这至少是实现 IUserStore 的某个组件。
编辑:
虽然您在评论中提到的解决方案可能有效,但这不是更好的解决方案,因为:
- Having multiple constructors is an anti-pattern
- 您现在正在使用服务定位器反模式从
HttpContext
解析 ApplicationUserManager
VS2013 附带的模板需要一些工作才能与依赖注入一起使用。这将花费一些时间。好消息是,它是可行且可行的,将大大提高您对 Owin
、Asp.Net Identity
、依赖注入和 SOLID design.
的了解
我在我的应用程序中使用 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 的问题,而不是我的代码。
我认为例外很明显。这可能是关于身份模板中的 AccountController,它带有 2 个构造函数。
StructureMap 默认使用 most greediest constructor。该模板带有 2 个构造函数,一个默认构造函数和一个带有 ApplicationUserManager
对象的构造函数。
如果没有 StructureMap,将调用默认构造函数,并且将使用 service locator anti pattern.
解析 ApplicationUserManagerStructureMap 现在必须创建 ApplicationUserManager
,因为这是一个具体类型,所以它会尝试。如果它是一个抽象的,它会在那里抛出异常。然而,ApplicationUserManager
有一个需要 IUserStore<Person>
的构造函数。因为这是一个抽象并且容器没有注册这种类型,所以 StructureMap 无法为您创建类型。
要解决此问题,您应该删除默认构造函数并注册 ApplicationUserManager 和相关服务,这至少是实现 IUserStore 的某个组件。
编辑: 虽然您在评论中提到的解决方案可能有效,但这不是更好的解决方案,因为:
- Having multiple constructors is an anti-pattern
- 您现在正在使用服务定位器反模式从
HttpContext
解析
ApplicationUserManager
VS2013 附带的模板需要一些工作才能与依赖注入一起使用。这将花费一些时间。好消息是,它是可行且可行的,将大大提高您对 Owin
、Asp.Net Identity
、依赖注入和 SOLID design.