Asp.net web api 具有多个WebAPI项目的简单注入器
我有一个包含多个WebAPI项目的C解决方案。其中一个项目,我们称之为项目A,已经成功地使用了SimpleInjector。我试图将SimpleInjector添加到这些WebAPI项目中的另一个,即项目B,但我面临一个问题 我正试图在项目B中创建第二个容器,就像在项目a中一样,但当我这样做并尝试构建解决方案时,在项目a中(在项目B之后构建)的容器中存在异常。请验证方法。它告诉我,位于项目B IUserService的接口没有在项目a正确注册,但项目a没有使用此接口 在Global.asax.cs的项目B中,我有以下配置:Asp.net web api 具有多个WebAPI项目的简单注入器,asp.net-web-api,simple-injector,Asp.net Web Api,Simple Injector,我有一个包含多个WebAPI项目的C解决方案。其中一个项目,我们称之为项目A,已经成功地使用了SimpleInjector。我试图将SimpleInjector添加到这些WebAPI项目中的另一个,即项目B,但我面临一个问题 我正试图在项目B中创建第二个容器,就像在项目a中一样,但当我这样做并尝试构建解决方案时,在项目a中(在项目B之后构建)的容器中存在异常。请验证方法。它告诉我,位于项目B IUserService的接口没有在项目a正确注册,但项目a没有使用此接口 在Global.asax.c
/* 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);
/* 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);
在项目A中,我有以下配置:
/* 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);
/* 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,或更改的构造函数
用户控制器
RegisterWebApp控制器使用封面下的反射来搜索ApicController的实现
我猜,根据您得到的错误,项目B被项目A引用,对项目A中container.RegisterWebApp控制器的调用也会找到并注册项目B的控制器
现在,当调用.Verify时,它将扫描项目B中APIController的构造函数,发现对IUserService的依赖并中断,因为项目a中实际上缺少此注册
集成包包含RegisterWebApp控制器的另一个重载,该重载接受必须为ApicController扫描的程序集数组,而不是扫描所有引用的程序集
假设项目A的程序集包含所有需要注册的APIController,则此重载可在项目A中使用,如:
container.RegisterWebApp控制器GlobalConfiguration.Configuration,
新[]{typeofmyapicontrolleringprojecta.Assembly};
RegisterWebApp控制器使用封面下的反射来搜索ApicController的实现
我猜,根据您得到的错误,项目B被项目A引用,对项目A中container.RegisterWebApp控制器的调用也会找到并注册项目B的控制器
现在,当调用.Verify时,它将扫描项目B中APIController的构造函数,发现对IUserService的依赖并中断,因为项目a中实际上缺少此注册
集成包包含RegisterWebApp控制器的另一个重载,该重载接受必须为ApicController扫描的程序集数组,而不是扫描所有引用的程序集
假设项目A的程序集包含所有需要注册的APIController,则此重载可在项目A中使用,如:
container.RegisterWebApp控制器GlobalConfiguration.Configuration,
新[]{typeofmyapicontrolleringprojecta.Assembly};
以下不是对您问题的回答,而是如何改进和简化项目a的注册的建议 我建议使用以下代码连接项目A的容器实例,而不是使用发布的代码:
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通过检查构造函数的依赖关系自动连接类型。
不仅简化了注册,而且现在Simple Injector知道完整依赖关系图的结构,因此可以有效地代表您进行验证。例如,这将允许简单的注入器找到任何。
ILog抽象使用条件注册。这允许Simple Injector注入特定于消费类型的ILog实现。这允许日志库记录有关原始类的信息。这在您的注册中是不起作用的,因为它总是向记录器注入包含您的注册的类型。
以下不是对您问题的回答,而是如何改进和简化项目a的注册的建议 我建议使用以下代码连接项目A的容器实例,而不是使用发布的代码:
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通过检查构造函数的依赖关系自动连接类型。
注册不仅简化了,而且现在变得简单了
ctor知道完整依赖关系图的结构,因此可以有效地代表您进行验证。例如,这将允许简单的注入器找到任何。
ILog抽象使用条件注册。这允许Simple Injector注入特定于消费类型的ILog实现。这允许日志库记录有关原始类的信息。这在您的注册中是不起作用的,因为它总是向记录器注入包含您的注册的类型。
所以现在的问题是:为什么OP从项目A引用项目B?对我来说,这似乎不是一个正确的设计。最好的办法是将公共性提取到一个新的程序集中,这两个项目都引用csn。所以现在的问题是:为什么OP引用项目a中的项目B?对我来说,这似乎不是一个正确的设计。最好的办法是将通用性提取到一个新的程序集中,这两个项目都引用了csn。在查看您的配置时,我不禁注意到,您很少使用容器创建实例的能力,并且自动注入了依赖项。您应该更喜欢这种方法,因为1。这将导致更简单的代码和2。允许简单的注入器为您检测错误。嘿@Steven!很高兴在这里见到你!你能给我解释一下我是怎么做的吗?我是DI World的新手,请查看我的注册替代方法的答案。在查看您的配置时,我忍不住注意到您很少使用容器创建实例并自动注入依赖项的能力。您应该更喜欢这种方法,因为1。这将导致更简单的代码和2。允许简单的注入器为您检测错误。嘿@Steven!很高兴在这里见到你!你能给我解释一下我是怎么做的吗?我是DI世界的新手,请查看我的答案,以获得注册的替代方法。