草庐IT

c# - 惰性依赖注入(inject)

coder 2023-07-13 原文

我有一个项目,其中 Ninject 被用作 IoC 容器。我担心的是很多类都有这样的构造函数:

[Inject]
public HomeController(
    UserManager userManager, RoleManager roleManager, BlahblahManager blahblahManager) {
   _userManager = userManager;
   _roleManager = roleManager;
   _blahblahManager = blahblahManager;
}

如果我不想一次拥有这些类的所有实例怎么办?

方式,当所有这些类都被 Lazy<T> 包装时并传递给构造函数并不是我所需要的。 T尚未创建实例,但是 Lazy<T>实例已经存储在内存中。

我的同事建议我使用工厂模式来控制所有实例化,但我不确定 IoC 是否存在如此大的设计错误。

对于这种情况是否有解决方法,或者 IoC 的设计真的有这么大的缺陷?也许我应该使用另一个 IoC 容器?

有什么建议吗?

最佳答案

在我看来你正在做premature optimization : 不要这样做。

你的服务的构造者应该做nothing more而不是将它所需要的依赖项存储在私有(private)字段中。在那种情况下,创建这样一个对象确实是轻量级的。不要忘记 .NET 中的对象创建速度非常快。在大多数情况下,从性能的角度来看,这些依赖项是否被注入(inject)并不重要。尤其是与应用程序的其余部分(以及您使用的框架)吐出的对象数量进行比较时。真正的成本是在您开始使用 Web 服务、数据库或文件系统(或一般的 I/O)时,因为它们会导致更大的延迟。

如果创作真的很昂贵,你通常应该把创作藏在Virtual Proxy后面。而不是注入(inject) Lazy<T>在每个消费者中,因为这允许通用应用程序代码忽略这样一个事实,即存在延迟创建的机制(当您这样做时,您的应用程序代码和测试代码都变得更加复杂)。

第 8 章 Dependency Injection: Principle, Practices, Patterns包含有关惰性代理和虚拟代理的更详细讨论。

然而,一个Lazy<T>只消耗 20 字节的内存(和另一个 24 bytes 用于它包装的 Func<T> ,假设一个 32 位进程),并创建一个 Lazy<T>实例几乎是免费的。因此无需担心这一点,除非您处于内存限制非常严格的环境中。

如果内存消耗是个问题,请尝试注册生命周期大于 transient 的服务。您可以针对每个请求、每个 Web 请求或单例进行处理。我什至会说,当您处于创建新对象存在问题的环境中时,您可能应该 only use singleton services (但您不太可能在这样的环境中工作,因为您正在构建 Web 应用程序)。

请注意,Ninject 是速度较慢的 .NET DI 库之一。如果这让你感到困扰,switch to a faster container .一些容器的性能接近于手动更新对象图。 但一定要分析一下,许多开发人员出于错误的原因切换 DI 库。

请注意 Lazy<T> 的使用因为依赖是一个 leaky abstraction (违反了 Dependency Inversion Principle )。请阅读this answer获取更多信息。

关于c# - 惰性依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12284487/

有关c# - 惰性依赖注入(inject)的更多相关文章

  1. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

    我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

  2. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  3. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  4. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  5. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  6. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  7. ruby - 这个 ruby​​ 注入(inject)魔术是如何工作的? - 2

    我今天看到了一个ruby​​代码片段。[1,2,3,4,5,6,7].inject(:+)=>28[1,2,3,4,5,6,7].inject(:*)=>5040这里的注入(inject)和之前看到的完全不一样,比如[1,2,3,4,5,6,7].inject{|sum,x|sum+x}请解释一下它是如何工作的? 最佳答案 没有魔法,符号(方法)只是可能的参数之一。这是来自文档:#enum.inject(initial,sym)=>obj#enum.inject(sym)=>obj#enum.inject(initial){|mem

  8. ruby - 有什么方法可以告诉 sidekiq 一项工作依赖于另一项工作 - 2

    有什么方法可以告诉sidekiq一项工作依赖于另一项工作,并且在后者完成之前无法开始? 最佳答案 仅使用Sidekiq;答案是否定的。正如DickieBoy所建议的那样,您应该能够在依赖作业完成时将其启动。像这样。#app/workers/hard_worker.rbclassHardWorkerincludeSidekiq::Workerdefperform()puts'Doinghardwork'LazyWorker.perform_async()endend#app/workers/lazy_worker.rbclassLaz

  9. ruby - 了解在 Ruby 中与 lambda 一起使用的 inject 行为 - 2

    我经常将预配置的lambda插入可枚举的方法中,例如“map”、“select”等。但是“注入(inject)”的行为似乎有所不同。例如与mult4=lambda{|item|item*4}然后(5..10).map&mult4给我[20,24,28,32,36,40]但是,如果我制作一个2参数lambda用于像这样的注入(inject),multL=lambda{|product,n|product*n}我想说(5..10).inject(2)&multL因为“inject”有一个可选的单个初始值参数,但这给了我......irb(main):027:0>(5..10).inject

  10. ruby - 有人可以解释一下在 Ruby 中注入(inject)的真实、通俗易懂的用法吗? - 2

    我正在学习Ruby,遇到了inject。我正处于理解它的风口浪尖,但当我是那种需要真实世界的例子来学习一些东西的人时。我遇到的最常见的例子是人们使用inject来添加一个(1..10)范围的总和,我不太关心这个。这是一个任意的例子。在实际程序中我会用它做什么?我正在学习,所以我可以继续使用Rails,但我不必有一个以Web为中心的示例。我只需要一些我可以全神贯注的目标。谢谢大家。 最佳答案 inject有时可以通过它的“其他”名称reduce更好地理解。它是一个对Enumerable进行操作(迭代一次)并返回单个值的函数。它有许多有

随机推荐