问题标签 [simple-injector]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
4593 浏览

c# - RegisterAll 与注册上下文的能力在哪里(又名 Func)?

我可以使用 instanceCreator 上下文(aka )注册单个注册项Func<T>,但 RegisterAll 似乎没有相同的限额。

TL;DR - 找到接受的答案并查看更新 2(或跳至此问题的更新 3)

这就是我想要做的:

我尝试根据先前的 Stack Overflow 答案为多个注册添加扩展,但似乎最后一个获胜:

我也很好奇为什么首先需要RegisterAll存在。这是我使用过的 5 个依赖注入容器中的第一个。其他的只是允许您针对服务注册多种类型,然后通过调用Resolve<IEnumerable<TService>>(autofac) 或GetAllInstances<TService>(SimpleInjector 和 Ninject) 将它们全部加载。

更新

为了更清楚起见,我正在尝试构建一个项目列表,我可以将其传递给处理每个单独项目的复合材料。它遇到了与上述相同的问题,因为它属于一组任务,这些任务都被注册为基于调度、触发器和事件 (Rx) 运行。暂时删除所有寄存器并删除其他一些内容:

你可以看到我正在抓取之前注册的文件观察者的所有实例。

我需要知道的是这个问题的简单解决方法以及何时实施(或者如果没有,为什么不会实施)。鉴于 Simple Injector 设计的当前限制,我也将接受这是不可能的。我不能接受的是我需要改变和调整我的架构以满足工具的限制。

更新 2

让我们谈谈 OCP(Open Closed Principle aka the O in SOLID)以及我在 SimpleInjector 在某些情况下如何打破这一特定原则的印象。

开闭原则就是这样,对扩展开放,对修改关闭。这意味着您可以在不更改其源代码的情况下更改实体的行为。

现在让我们转向一个相关的例子:

注意那是多么干净。为了能够做到这一点,我需要能够注册接口的所有实例:

对?所以这里的教训是,这很好并且符合 OCP。我可以通过添加或删除已注册的项目来更改任务运行器的行为。打开扩展,关闭修改。

现在让我们专注于尝试按照以下答案中建议的方式进行操作(在第二次更新之前,最终回答了这个问题),作者给人的印象是更好的设计。

让我们从维护者提到的良好注册设计开始。我得到的观点是我必须牺牲我的代码以某种方式使 ITask 更灵活地使用 SimpleInjector:

现在让我们看看这如何改变我们的设计:

哎哟。您可以看到每次我从容器注册中添加或删除项目时,我现在还需要更新另一段代码。一个更改的两个修改位置,我打破了多个设计问题。

你可能会说我为什么要向容器索要这个?好吧,这是在启动领域,但如果我不是,让我们探索一下。

所以我将使用构造函数注入来说明为什么这是不好的。首先让我们将我的示例视为构造注入。

干净整洁。

现在,让我们切换回我对已接受答案观点的理解(同样在更新 2 之前):

哎哟。每次我必须编辑多个代码区域时,我们甚至都不要开始了解这个设计有多糟糕。

这里有什么教训?我不是世界上最聪明的人。我维护(或尝试维护:))多个框架,并且我不会假装我比其他人了解更多或更好。我的设计感可能是有偏差的,或者我可能会以某种我还没有想到的未知方式限制其他人。我敢肯定,作者在提供设计建议时是善意的,但在某些情况下,它可能会让人讨厌(而且有点居高临下),尤其是对于我们这些知道自己在做什么的人来说。

更新 3

因此,维护者在更新 2 中回答了这个问题。我试图使用 RegisterAll,因为我没有想到我可以使用Register<IEnumerable<T>>(不幸的是文档没有指出这一点)。现在看起来很明显,但是当人们从其他 IoC 框架中跳出来时,他们背负着一些包袱,可能会错过设计中的这种令人敬畏的简化!我错过了,我的腰带下还有 4 个其他 DI 容器。希望他将其添加到文档中或更好地调用它。

0 投票
1 回答
6038 浏览

c# - 如何使用依赖注入从多个来源获取配置?

我正在使用 Simple Injector,但也许我需要的是更多概念性的答案。

这是交易,假设我的应用程序设置有一个界面:

然后,通常会有一个实现 IApplicationSettings 的类,从指定的源获取每个字段,例如:

然而!假设我想EnableLogging从 app.config、CopyLocal数据库和ServerName另一个获取当前计算机名称的实现中获取。我希望能够混合匹配我的应用程序配置,而不必创建 9 个实现,每个组合一个。

我假设我不能传递任何参数,因为接口是由注入器(容器)解析的。

我一开始是这么想的:

但是,有了这个我有一个主要问题:我怎么知道如何创建一个TEnableLogging(它是 a IGetValue<bool>)的实例?哦,假设这IGetValue<bool>是一个具有 Value 属性的接口,它将由具体类实现。但是具体的类可能需要一些细节(比如 app.config 中的键名是什么)或不需要(我可能只是想始终返回 true)。

我对依赖注入比较陌生,所以也许我的想法是错误的。有没有人对如何做到这一点有任何想法?

(你可以用另一个 DI 库来回答,我不介意。我想我只需要抓住它的概念。)

0 投票
1 回答
200 浏览

c# - 使用 DI 创建带有上下文的插件实例

我正在重构我们的应用程序以包含依赖注入(通过构造函数注入)并且遇到了一个棘手的极端情况:

我们目前有一些ImageViewer对象,在实例化时会在程序集中搜索ImageViewerPlugin(抽象基类)实例,并使用反射实例化它们。这是在ImageViewer使用方法的构造函数中完成的(在所有具体插件类型的循环中调用),类似于:

ImageViewerPlugin 类大致如下所示:

一个具体的实现大致是这样的:

每个ImageViewer实例都有自己的ImageViewerPlugin实例集合。

现在应用程序被重构为使用 DI 容器和构造函数注入,我发现这些插件具有需要由 DI 容器解决的依赖项(以前通过使用全局静态类隐藏),但我不知道如何在不使用服务定位器(反模式)的情况下做到这一点。

最明智的解决方案似乎是使用 DI 创建这些插件实例。这将允许我添加额外的构造函数参数,以通过构造函数注入注入它们所依赖的依赖项。但是如果我这样做,我如何viewer在注入其余参数值的同时传递特定的参数值?

我认为 anImageViewerPluginFactory将有助于实现这一点,但看不到如何实现这样的工厂,因为每个插件都可能具有不同的构造函数签名。

我该如何解决这种情况?还是我以完全错误的方式接近这个?

0 投票
1 回答
165 浏览

c# - SimpleInjector container.RegisterSingleOpenGeneric 不返回相同的实例

我已经注册了一个“开放通用类型”,如下所示:

然后我尝试按照以下方式检索实例两次:

t1应该等于t2,考虑到我正在使用RegisterSingleOpenGeneric?

在下面, b 等于false- 如果它相同,它应该是正确的,对吧?

0 投票
2 回答
53159 浏览

c# - Simple Injector 无法在 Web API 控制器中注入依赖项

我正在尝试使用 Simple Injector 做一些基本的构造函数 DI,它似乎无法解决 Web API 控制器的依赖关系。

  • 我在“API”文件夹中有一个 API 控制器,它位于“Controllers”文件夹之外。
  • 我也尝试将它放在“Controllers”文件夹中,但这似乎没有太大区别。我收到的堆栈跟踪类似于此问题中提供的堆栈跟踪。
  • 我正在使用全新安装的“Simple Injector MVC Integration Quick Start”NuGet Package (v. 2.1.0)。
  • 我有来自文档的基础,这也与在此处SimpleInjectorWebApiDependencyResolver找到的相同。
  • 我正在使用实体框架,并查看了有关更改以正确加载上下文的讨论线程。

这似乎不是问题,但我仍然收到以下错误:

类型“MyProject.API.ArticleController”没有默认构造函数

System.ArgumentException 在

System.Linq.Expressions.Expression.New(Type type) at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType , Func`1& activator) 在 System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)

如果有人能给我一些建议,关于是否应该从当前状态/呼叫顺序修改任何内容,我们将不胜感激。

ArticleController(基本结构):

SimpleInjectorInitializer:

全球.asax.cs:

0 投票
1 回答
287 浏览

c# - 使用 IIS Express / Visual Studio 的 SimpleInjector 验证过程

我的解决方案中内置了一个专有事件模型,它有一个订阅实例化过程,该过程使用GetAllInstances()SimpleInjector 的方法来定位事件的所有订阅者

根据我是否注册所有实例,我的性能会出现巨大ISubscriber差异

这是我用来注册的代码ISubscriber

当我在没有调用RegisterManyForOpenGeneric容器验证的情况下引导容器时,大约需要 11 秒并返回结果:

配置警告:未检测到警告。

注册:计数 = 158

但是,当我取消注释对RegisterManyForOpenGeneric容器验证的调用大约需要 72 秒并返回结果时:

配置警告:已检测到 136 个容器注册类型,这些类型被 181 个组件引用

注册:计数 = 475

我的问题是——这样可以吗,还是我在这里做错了什么?我一直在添加更多ISubscriber的课程,现在启动(方式)太慢了......


更新

这似乎只是在 Visual Studio中运行的 WebAPI 项目的问题。从控制台应用程序引导需要 15 秒在 Visual Studio 中运行。将 WebAPI 项目部署到 IIS 后,验证需要 6 秒。

0 投票
1 回答
1390 浏览

c# - 将 Autofac 转换为 Simple Injector

在 Autofac 我可以执行以下操作

GreetService 继承自 ServiceBase 的地方

我想用 Simple Injector 做同样的事情。

有人知道怎么做吗?

谢谢

更新 1

我发现这篇文章他们在 Windows 服务中使用 autofac:http ://www.turbulentintellect.com/2011/02/anatomy-of-windows-service-part-2.html

我一直在尝试用 Simple Injector 替换 Autofac,但我无法安装生成的服务。我收到的错误是 System.ArgumentException:必须为源指定值。这通常表示 ServiceInstaller 和 Service 中的 ServiceName 不匹配。

除以下内容外,所有内容均按照文章进行设置:

我肯定在这里遗漏了一些东西,但似乎无法弄清楚是什么。

更新 2

当我使用 InstallUtil 安装服务时,我在安装日志中收到以下信息

运行事务安装。

开始安装的安装阶段。查看日志文件的内容以了解 C:\Local Development\HelloSvc\HelloSvc\bin\Debug\HelloSvc.exe 程序集的进度。该文件位于 C:\Local Development\HelloSvc\HelloSvc\bin\Debug\HelloSvc.InstallLog。

安装阶段发生异常。System.ArgumentException:必须为源指定值。

安装的回滚阶段即将开始。查看日志文件的内容以了解 C:\Local Development\HelloSvc\HelloSvc\bin\Debug\HelloSvc.exe 程序集的进度。该文件位于 C:\Local Development\HelloSvc\HelloSvc\bin\Debug\HelloSvc.InstallLog。

回滚阶段成功完成。

事务安装已完成。

如前所述,这通常是因为 ServiceName 设置不正确,但我看不出在这种情况下这是怎么可能的。

谢谢

0 投票
2 回答
3122 浏览

c# - C# 单元测试 - 模拟、存根或使用显式实现

这个之前已经讨论过很多次了,但是下面例子中的优点并不明显,所以请多多包涵。

我正在尝试决定是否在我的单元测试中使用模拟实现,并且鉴于以下两个示例,我尚未决定,第一个使用 NSubstitute 进行模拟,第二个使用 SimpleInjector(Bootstrapper 对象)解析的实现。

本质上,两者都在测试同一件事,即在调用 .Dispose() 方法时将 Disposed 成员设置为 true(请参阅本文底部的方法实现)。

在我看来,第二种方法对回归测试更有意义,因为模拟代理在第一个示例中将 Disposed 成员显式设置为 true,而在注入实现中它是由实际的 .Dispose() 方法设置的。

您为什么建议我选择一个而不是另一个来验证该方法是否按预期运行?即调用了 .Dispose() 方法,并且该方法正确设置了 Disposed 成员。

作为参考, .Dispose() 方法就是这样:

干杯

0 投票
1 回答
900 浏览

c# - SimpleInjector - 如何使用 LifetimeScopeLifestyle 注册许多泛型类型的实现?

在回答这个问题时,我无法找出使用LifetimeScopeLifestyleSimpleInjector 中的实例注册许多泛型类型实现的最佳技术。

这种注册形式的推荐方法是这样的:

但这不允许LifetimeScopeLifestyle传入的实例。

下面是我想出的,但我知道它没有足够的弹性,因为它正在检查任何通用接口,而不是专门IRepository<>的 . 谁能告诉我该怎么做?

0 投票
1 回答
939 浏览

c# - Membus 和 Simple Injector - 通过接口自动连接命令处理程序

我在 Membus 中看到了 IoC 功能,我尝试将其连接到 Simple Injector

这个想法是我将自动注册我的所有类型RegisterManyForOpenGeneric(typeof<CommandHandler<>),typeof<CommandHandler<>).Assembly)

毫无疑问,通常有充分的理由,SimpleInjector 不允许多次注册 - 但是,我想这样做是为了让不同的处理程序实现命令处理的不同方面/问题。

当然,IEnumerable<object> IocAdapter.GetAllInstances(Type desiredType)来自 membus 的接口需要一个集合,因此可以调用多个处理程序。

将 Membus 与 SimpleInjector IoC 结合的最佳方式是什么?

脚注

我已经看到了按照惯例连接menbus的其他方法:

但我真的很想坚持使用 IoC 容器来处理生命周期范围,并避免实例化命令处理程序并在需要它们之前手动连接它们。