- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在读这本书 Dependency Injection in .NET马克西曼。在这本书中,他推荐了注册、解决、发布模式,还建议这些操作中的每一个都应该在您的应用程序代码中只出现一次。
我的情况如下:我正在创建一个应用程序,它使用专有通信协议(protocol)与 PLC(一种工业嵌入式计算机)通信,PLC 制造商为其提供了一个库。该库的文档建议创建到 PLC 的连接并保持打开状态;然后使用计时器或 while 循环,应定期发送请求以读取 PLC 内存中随时间变化的内容。
从 PLC 的内存中读取的值应该用于对数据库进行操作,为此我打算使用 Entity Framework 。据我了解,最好的选择是在每次循环执行时创建一个新的 dbContext
以避免停顿缓存或并发问题(循环可能每隔几毫秒执行一次很长一段时间连接一直保持打开的时间)。
我的第一个选择是在应用程序构建时调用 Resolve 以创建一个长期存在的对象,该对象将与 PLC 通信对象一起注入(inject)并处理循环执行并保持连接有效。然后,在每次循环执行开始时,我打算再次调用 Resolve 以创建一个短期对象,该对象将被注入(inject)一个新的 dbContext
并在数据库上执行操作。然而,在阅读了那本书的建议后,我怀疑我是否走在正确的轨道上。
我的第一个想法是在构造时将委托(delegate)传递给长生命周期对象,这将允许它构建短生命周期对象的新实例(我相信这是工厂模式),从而消除对来 self 长期存在的对象的 DI 容器。然而,这个构造仍然违反了上述模式。
在这种情况下,哪种方式才是处理依赖注入(inject)的正确方法?
我第一次没有 DI 的尝试:
class NaiveAttempt
{
private PlcCommunicationObject plcCommunicationObject;
private Timer repeatedExecutionTimer;
public NaiveAttempt()
{
plcCommunicationObject = new PlcCommunicationObject("192.168.0.10");
plcCommunicationObject.Connect();
repeatedExecutionTimer = new Timer(100); //Read values from PLC every 100ms
repeatedExecutionTimer.Elapsed += (_, __) =>
{
var memoryContents = plcCommunicationObject.ReadMemoryContents();
using (var ctx = new DbContext())
{
// Operate upon database
ctx.SaveChanges();
}
}
}
}
第二次尝试使用穷人的 DI。
class OneLoopObject
{
private PlcCommunicationObject plcCommunicationObject;
private Func dbContextFactory;
public OneLoopObject(PlcCommunicationObject plcCommunicationObject, DbContext dbContext
{
this.plcCommunicationObject = plcCommunicationObject;
this.dbContext = dbContext;
}
public void Execute()
{
var memoryContents = plcCommunicationObject.ReadMemoryContents();
// Operate upon database
}
}
class LongLivedObject
{
private PlcCommunicationObject plcCommunicationObject;
private Timer repeatedExecutionTimer;
private Func oneLoopObjectFactory;
public LongLivedObject(PlcCommunicationObject plcCommunicationObject, Func oneLoopObjectFactory)
{
this.plcCommunicationObject = plcCommunicationObject;
this.dbContextFactory = dbContextFactory;
this repeatedExecutionTimer = new Timer(100);
this.repeatedExecutionTimer.Elapsed += (_, __) =>
{
var loopObject = oneLoopObjectFactory(plcCommunicationObject);
loopObject.Execute();
}
}
}
static class Program
{
static void Main()
{
Func oneLoopObjectFactory = plc => new OneLoopObject(plc, new DbContext());
var myObject = LongLivedObject(new PlcCommunicationObject("192.168.1.1"), oneLoopObjectFactory)
Console.ReadLine();
}
}
1 Câu trả lời
第一版指出(第 3 章,第 82 页):
In its pure form, the Register Resolve Release pattern states that you should only make a single method call in each phase [...] an application should only contain a single call to the
Resolve
phương pháp.
此描述源于您的应用程序仅包含一个根对象(通常在编写简单的控制台应用程序时)或一组逻辑根类型的想法,例如MVC Controller 。例如,对于 MVC Controller ,您将拥有一个自定义 Controller 工厂,它由 MVC 框架提供,并带有要构建的 Controller 类型。在这种情况下,该工厂在提供类型时只会调用一次 Resolve
.
但是,在某些情况下,您的应用程序有多个根类型组。例如,Web 应用程序可以混合使用 API Controller 、MVC Controller 和 View 组件。对于每个逻辑组,您可能会在应用程序中对 Resolve
进行一次调用,因此对 Resolve
进行多次调用(通常是因为每个根类型都有自己的工厂)。
回调容器还有其他正当理由。例如,您可能希望推迟构建对象图的一部分,以解决 Captive Dependencies 的问题。 .这似乎是你的情况。进行额外解析的另一个原因是当您使用调解器模式将消息分派(dispatch)给可以处理该消息的特定实现(或多个实现)时。在那种情况下,您的调解器实现通常会包装容器并调用 Resolve
。 Mediator 的抽象可能会在您的域库中定义,而 Mediator 的实现及其对容器的了解应该在 inside Composition Root 中定义。 .
因此,不应按字面意思理解对 Resolve
进行一次调用的建议。这里的实际目标是在一次调用中尽可能多地构建一个对象图,而不是让类自己回调到容器中来解决它们的依赖关系(即 Service Locator anti-pattern ).
本书提出的另一个重要观点(second edition)是
Querying for Dependencies, even if through a DI Container, becomes a Service Locator if used incorrectly. When application code (as opposed to infrastructure code) actively queries a service in order to be provided with required Dependencies, then it has become a Service Locator.
A DI Container encapsulated in a Composition Root isn't a Service Locator—it's an infrastructure component.
(注意:此引用来自 second edition ;虽然第一版也包含此信息,但表述可能有所不同)。
因此 RRR 模式的目标是促进组合根中 DI 容器的封装,这就是它坚持对 Resolve
进行一次调用的原因。
请注意,在编写 second edition 时, Mark 和我想重写对 RRR 模式的讨论。这样做的主要原因是我们发现文本令人困惑(如您的问题所示)。然而,我们最终没时间了,所以我们决定简单地删除那个详尽的讨论。我们认为最重要的几点已经提出。
关于c# - 注册、解决、 Release模式使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53268326/
我认为我的问题与“https://serverfault.com/q/299179”和“https://serverfault.com/q/283330/71790”有些相关,但其中任何一个都没有令我
我生成了 APK 对于我的 flutter 项目和 F:\build\app\outputs\apk\release 我有 3 种类型的 apk 文件,包括 output.json 文件。他们是: *
我们最近决定更新 Beta release 的新应用程序在 Google Play 上, 现在读完指南后,我心里有一些问题,想了解更多,我用谷歌搜索进一步了解找到了一些答案,但还有一些我不确定的东西,
我正在尝试使用发布管理作为构建版本的工具,但我很难理解码件、工具和操作之间的真正区别。有人可以分解这三个概念之间的差异以及它们如何相互配合吗? 最佳答案 由于它适用于基于代理的版本: 工具旨在提供自定
我最近完成了使用 jgitflow:release-finish 合并一个发布分支来掌握和开发。 .构建成功。 但是现在我正在尝试使用 jgitflow:releast-start 创建一个新分支.但
Tôi đã đọc rằng nếu một bộ sưu tập được "phát hành" thì nó cũng sẽ phát hành tất cả các đối tượng của nó. Mặt khác, tôi cũng đọc rằng một bộ sưu tập sẽ giải phóng các đối tượng của nó khi bộ sưu tập đó được giải phóng. Nhưng điều cuối cùng đó không phải lúc nào cũng xảy ra, như Apple đã nói. Hệ thống quyết định xem có nên hủy phân bổ hay không. Trong hầu hết các trường hợp
我在具有以下布局的多模块项目上使用 maven-release-plugin: ROOT/ + parent + module1 + module2 在parent的pom中,使用modu
我正在使用 ionic 构建移动应用。 我面临一个严重的问题。 我必须使用 on-touch 和 on-release 事件,但问题是每当我触摸时,on-release 甚至也会立即触发而没有实际释放
谁能解释清楚两者之间的区别是什么.Release()和->Release() 在 CComPtr 上? 确切地说,两种情况下内存管理是如何发生的? 最佳答案 CComPtr 的operator-> 函
两个片段有什么区别? [myObj release]; 和 [myObj release]; myObj = nil; 最佳答案 如果你只是释放一个对象,那么它就会变成释放对象。 如果您尝试对已释放的
我正在运行 maven 发布插件 (org.apache.maven.plugins:maven-release-plugin:2.3.2) 并注意到当通过命令行。我想知道是否有办法关闭它。 我使用
我正在尝试通过运行nuget pack -properties Configuration=Release命令来更新我的nuget软件包,但这会给我以下错误: Unable to find 'bin/
我们正在使用 Microsoft 的发布管理将我们的 Web 应用程序部署到我们的测试环境 (QA)。它是一个直接的 MVC.Net Web 应用程序。我们的构建生成一个 web 部署包,我们有一个命
我有一个在 X 环境中发布的版本 A。另一方面,我有一个在环境 Y 中发布的版本 B。 问题是我想知道我是否可以在版本 B 中检查版本 A 的状态,这样我就可以抛出错误而不发布版本 B。 我不知道是否
我正在开发一个使用大量图像的应用程序,我正在使用 UIWebView 使用 JavaScript 代码(我正在使用 UIZE 库)来表示大约 200 张图像,问题当我完成 UIWebView 时,我在
我已阅读 Marshal.GetIUnknownForObject 的文档它说: Always use Marshal.Release to decrement the reference count
为了成为 iPhone SDK 上的好内存公民,我一直在玩内存。 然而,我仍然很难理解"self.something" 和只是"something" 之间的区别。 据我了解,"self.somethi
我需要使用 bash 找出我正在运行的 Linux 发行版。找到this page ,这非常有帮助。 但是我的系统有两个/etc/*-release 文件 /etc/lsb-release /etc/
我想使用 Maven Release Plugin 将 Release Candidates 发布到我的 Nexus Snapshot 存储库。 将 RC 部署到 Nexus 不是问题,但我想利用 m
在什么情况下我们应该使用“Latch until release”而不是“Switch until release”? 根据 LabVIEW 2011 Help : Latch until relea
Tôi là một lập trình viên xuất sắc, rất giỏi!