具有多个WebAPI项目的简单注入器

时间:2018-10-29 18:20:02

标签: asp.net-web-api simple-injector

我有一个包含多个WebAPI项目的C#解决方案。这些项目之一(称为项目A)已经成功使用了SimpleInjector。我正在尝试将SimpleInjector添加到这些WebAPI项目B中的另一个项目,但是我遇到了问题。

我正在尝试像在项目A中一样在项目B中创建第二个容器,但是当我这样做并尝试构建解决方案时,在项目B之后构建的项目A中有例外。 container.Verify()方法。它告诉我位于项目B(IUserService)上的接口未在项目A上正确注册,但是项目A没有使用此接口。

在Global.asax.cs的项目B中,我具有以下配置:

/* Dependency Injection */
var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();


container.Register<IUserService>(() => { return new UserService(); }, Lifestyle.Scoped);
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

container.Verify();

GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

在项目A中,我具有以下配置:

/* Dependency Injection */
var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

container.Register<ILog>(() => { return LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); }, Lifestyle.Scoped);
container.Register<IFundRepository>(() => { return new IporangaFundRepository(dbConnectorMiddle); }, Lifestyle.Scoped);
container.Register<ITradeRepository>(() => { return new IporangaTradeRepository(dbConnectorMiddle, middleReadClient); }, Lifestyle.Scoped);
container.Register<ITradeManager, TradeManager>(Lifestyle.Scoped);

container.Register<ITradeService>(() => new TradeService(container.GetInstance<ITradeManager>()),Lifestyle.Scoped);
container.Register<ISimulationService>(() => new SimulationService(container.GetInstance<ITradeService>()), Lifestyle.Scoped);
container.Register<IBookerService>(() => new BookerService(container.GetInstance<ITradeService>(), container.GetInstance<ISimulationService>()), Lifestyle.Scoped);
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

container.Verify();

GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

错误消息:

  

System.InvalidOperationException:'配置无效。   为UserController类型创建实例失败。构造函数   类型的UserController包含名称为“ userService”的参数   并键入未注册的IUserService。请确保   IUserService已注册,或更改的构造函数   UserController。'

2 个答案:

答案 0 :(得分:4)

以下内容不是您问题的答案,而是有关如何改善和简化A项目注册的建议。

我建议使用以下代码代替Project A的Container实例,而不是使用发布的代码:

var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

// For Log4NetAdapter<T>, please see: https://stackoverflow.com/a/25113659
container.RegisterConditional(typeof(ILog),
    c => typeof(Log4NetAdapter<>).MakeGenericType(c.Consumer.ImplementationType),
    Lifestyle.Singleton,
    c => true);

container.RegisterInstance(dbConnectorMiddle);
container.RegisterInstance(middleReadClient);

container.Register<IFundRepository, IporangaFundRepository>(Lifestyle.Scoped);
container.Register<ITradeRepository, IporangaTradeRepository(Lifestyle.Scoped);
container.Register<ITradeManager, TradeManager>(Lifestyle.Scoped);

container.Register<ITradeService, TradeService>(Lifestyle.Scoped);
container.Register<ISimulationService, SimulationService>(Lifestyle.Scoped);
container.Register<IBookerService, BookerService(Lifestyle.Scoped);

container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

container.Verify();

GlobalConfiguration.Configuration.DependencyResolver =
    new SimpleInjectorWebApiDependencyResolver(container);

这更好,因为:

  • 简化了注册,因为它们仅指定抽象(例如ITradeService)和实现(例如TradeService)之间的映射,而让Simple Injector Auto-Wire 通过检查构造函数的依赖关系来确定类型。
  • 不仅简化了注册,而且现在Simple Injector知道了完整依赖关系图的结构,因此可以代表您有效地进行验证。例如,这将允许Simple Injector查找任何Lifestyle Mismatches
  • 条件注册用于ILog抽象。这允许Simple Injector注入特定于消费类型的ILog实现。这使您的日志记录库可以记录有关原始类的信息。这在您的注册中不起作用,它总是会注入一种包含您的注册的记录器。

答案 1 :(得分:3)

RegisterWebApiControllers在幕后使用反射来搜索ApiController的实现。

我猜,基于您得到的错误,项目B引用了项目B,并且对项目A中的container.RegisterWebApiControllers的调用也找到并注册了项目B的控制器。

现在,当调用.Verify()时,它将扫描项目B中ApiControllers的构造函数,找到对IUserService的依赖关系并中断,因为该注册实际上在项目A中丢失了。 / p>

集成软件包还包含RegisterWebApiControllers的另一个重载,该重载采用必须扫描ApiControllers的程序集数组,而不是扫描所有引用的程序集。

假设项目A的程序集包含所有需要注册的ApiControllers,则此重载可以在项目A中使用,例如:

container.RegisterWebApiControllers(GlobalConfiguration.Configuration,
         new[] {typeof(MyApiControllerInProjectA).Assembly});