如何创建一个 Ninject 自定义作用域,在该对象被释放之前返回相同的对象?

2024-02-07

在 Ninject 中,在单例范围内声明绑定意味着每次都会返回相同的对象。永远只能有一个对象。

我想要的是一次返回一个对象。换句话说:

  1. 第一次调用 Get() 实例化一个新对象并返回它。
  2. 对 Get() 的后续调用返回相同的实例。
  3. 该对象已被处置。
  4. 对象被释放后对 Get() 的第一次调用会实例化一个新的/第二个对象并返回该对象。
  5. 对 Get() 的后续调用将返回在步骤 4 中创建的对象。

EDIT:这个问题实际上很容易解决,使用提供者 https://github.com/ninject/ninject/wiki/Providers,-Factory-Methods-and-the-Activation-Context并让相关对象在处置时引发事件。我很好奇是否有办法使用 Ninject 中的范围来做到这一点,并将这个问题留在这里,因为 Steven 的回答非常好。


由于您想在多线程应用程序中使用此构造,并希望跨线程重用同一实例(正如您在评论中暗示的那样),因此您将无法通过配置 DI 容器来解决此问题。

由于竞争条件,您根本无法将对象配置为在处置后更新。想象一下以下场景:

  1. 线程 1 向容器请求一个实例。
  2. 这是第一个请求,容器将创建一个新实例。
  3. 线程2向容器请求一个实例
  4. 容器返回在步骤 2 中创建的实例。
  5. 线程 1 完成实例并调用Dispose.
  6. 线程 2 开始使用该实例,但该实例已被释放,并引发异常。

问题是应用程序将获得对可以释放的实例的引用。

如果可以的话,尝试通过重新设计您的应用程序来防止这种情况发生。公开实现的服务类型是一种不好的做法IDisposable, 因为IDisposable是一个有漏洞的抽象。我个人的偏好甚至是阻止这些服务的任何实现IDisposable。在大多数情况下,重新设计可以让您不必这样做。

如果您需要使用IDisposable对象,通常的方法是创建并注入创建这些对象的工厂IDisposable对象。这样,消费者就可以安全地处置此类物品,没有任何问题。

这里的普遍问题是很难创建实现IDisposable,这实际上是线程安全的。

如果你真的想要这个,你可以尝试创建一个执行引用计数的装饰器。例如,看看下面的装饰器。它包裹着一个IService并实施IService. IService实施IDisposable。装饰器需要一个Func<IService> 允许创建实例的委托。对象的创建和处置受到保护lock语句和装饰器计算调用者对它的引用。在最后一个消费者处置装饰器之后,它将处置该对象并创建一个新对象。

public class ScopedServiceDecorator : IService
{
    private readonly object locker = new object();
    private Func<IService> factory;
    private IService currentInstance;
    private int referenceCount;

    public ScopedServiceDecorator(Func<IService> factory)
    {
        this.factory = factory;
    }
    public void SomeOperation()
    {
        IService instance;
        lock (this.locker)
        {
            instance = this.GetInstance();
            this.referenceCount++;
        }

        instance.SomeOperation();
    }

    public void Dispose()
    {
        IService instance = null;

        lock (this.locker)
        {
            this.referenceCount--;

            if (this.referenceCount == 0)
            {
                instance = this.wrappedService;
                this.wrappedService = null;
            }
        }

        // Dispose the object outside the lock for performance.
        if (instance != null)
        {
            instance.Dispose();
        }
    }

    private IService GetInstance()
    {
        if (this.wrappedService == null)
        {
            this.wrappedService = this.factory();
        }

        return this.wrappedService;
    }
}

请注意,由于以下原因,此实现仍然存在缺陷:

  1. Calling Dispose多次破坏装饰器。
  2. 当消费者致电SomeOperation多次(或IService有多种方法)执行将会中断。

创建一个按预期工作的装饰器是相当困难的。执行此操作的一种简单方法是序列化对对象的访问,但是当您执行此操作时,您可能希望每个线程使用单个实例。那会容易得多。

我希望这有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何创建一个 Ninject 自定义作用域,在该对象被释放之前返回相同的对象? 的相关文章

  • MVC和依赖注入,被迫使用单例Controller?

    我正在致力于构建一个根据 MVC 原则运行并利用依赖注入的 PHP 框架 我想我已经把前端控制器部分放下了 有一个工作路由器实例化控制器实例并根据请求的 URI 调用适当的操作 接下来是依赖注入 我想实现一个使用反射解决依赖关系的容器 这样
  • Autofac 无法解析构造函数的参数“System.String applicationClientId”

    我有以下类 接口结构 class ProviderSetting public delegate ProviderSetting Factory string applicationClientId string appKey public
  • 用作 ServiceStack 的 IoC 时在 autofac 中配置生命周期范围

    我目前正在使用 AutoFac 作为我们的 ServiceStack Web 服务应用程序的 DI 容器 我能够配置接线和所有内容 但在阅读了有关范围的部分后 我不知道在注册我的组件时最好使用哪个范围 在我们的特定情况下 我认为 PerHt
  • 这是依赖注入吗?这是一种不好的做法吗?

    我有一个小框架 我是这样编码的 我不确定这是否称为依赖注入 我不知道它是否像设计模式 我也不知道并且想知道是否通过 this因为 param 是一种不好的做法 看看这个 不是一个有效的示例 只是将这些代码写入浏览器中以供解释 This is
  • ASP.NET Web API 依赖注入

    我想知道是否可以在 ASP NET Web API 中进行依赖项注入 自定义构造函数 而无需使用第三方库 例如 Unity 或 StructureMap 且无需实体框架 我想要实现的是拥有一个带有构造函数的控制器 例如 public Con
  • AngularJS - 服务、工厂、过滤器等中的依赖注入

    因此 我想在我的 Angular 应用程序中使用一些插件和库 目前 我只是引用这些函数 方法 因为它们是在 99 的应用程序中以完全忽略依赖注入的方式使用的 我有 例如 javascript 库 MomentJS 它处理格式化和验证日期 并
  • 在简单注入器中解析具有自定义参数的类

    我正在使用以下命令创建 WPF MVVM 应用程序简易注射器作为 DI 容器 现在 当我尝试从简单注入器解析视图时遇到一些问题 因为我需要在构造时将参数传递到构造函数中 而不是在将视图注册到容器时 因此这不是适用的 简单注入器将值传递到构造
  • 有没有一种简单的方法来为每个类创建一个记录器实例?

    我现在使用静态方法来记录 因为我发现在Android中登录非常容易 但是现在我需要为不同的类配置不同的appender 所以我对静态记录方法有一个问题 我读了Log4J 创建 Logger 实例的策略 https stackoverflow
  • 如何调试symfony2服务容器中配置的标签和服务?

    我正在编写一个服务来处理 AccessDeniedException 并且我找到了一种方法来解决它使用 Symfony2 的 AccessDeniedHandlerInterface https stackoverflow com ques
  • javax.inject.Named 注释的用途是什么?

    我正在尝试理解javax inject包 我不清楚是什么javax inject Named注释应该用于 Javadoc 没有解释其背后的想法 Javadoc 位于http download oracle com javaee 6 api
  • Javascript:使用 IIFE 和块语句之间的区别

    IIFE主要用于封装作用域 function let myVar 10 not global 但为什么不直接使用块语句呢 let myVar 10 also not global 除了范围封装之外 进一步使用 IIFE 是否还有其他好处 块
  • 如何创建一个非单例的 Angular JS 服务?

    因为每个服务都是单例 调用 injector get 每次仍然给我相同的实例 如何在另一个服务中使用一个服务的多个实例 请记住 我的非单例类的声明不得污染全局命名空间等 我的示例如下 我希望 injector get serviceCall
  • 从 array_map 匿名函数内部调用类方法

    我正在尝试从一个对象中调用我的对象的方法之一array map匿名函数 到目前为止 我收到了预期的错误 致命错误 不在对象上下文中时使用 this 我知道为什么我会收到此错误 我只是不知道如何实现我想要的目标 有人有任何建议吗 这是我当前的
  • 异常处理的范围规则是什么? [复制]

    这个问题在这里已经有答案了 我偶然发现了一个有趣的场景这个问题 https stackoverflow com q 69464430 6045800 考虑以下简单示例 try 1 0 error error except Exception
  • 我可以在 Orchard CMS 中使用我的 Ninject .NET 项目吗?

    我正在使用 Orchard CMS 创建一个网站 并且有一个用 Ninject 编写的外部 NET 项目 用于依赖注入 我想将其与 Orchard CMS 中的模块一起使用 我知道 Orchard 使用 Autofac 进行依赖注入 这给我
  • 如何在 servlet 线程中获取新的有状态会话 bean?

    我正在尝试 EJB3 我想将一个有状态会话 bean 注入到 servlet 中 以便每个访问该 servlet 的用户都会获得一个新的 bean 显然 我不能让 bean 成为 servlet 的实例变量 因为它将被共享 显然不允许注入局
  • 动态菜单创建IoC

    我想知道是否有人知道我如何创建如何使用 AutoFac 之类的东西来让我动态地允许 dll 创建自己的表单和菜单项以在运行时调用它们 所以如果我有一个 员工 dll 新入门表格 证书表格 供应商 dll 供应商详细信息来自 产品形态 在我的
  • 与仅调用依赖函数/类相比,在 FastAPI 中使用 Depends 有哪些优点?

    FastAPI 提供了way https fastapi tiangolo com tutorial dependencies 通过其自己的依赖关系解析机制来管理依赖关系 例如数据库连接 它类似于一个pytest夹具系统 简而言之 您在函数
  • 嵌套函数中的变量作用域

    有人可以解释为什么以下程序失败 def g f for in range 10 f def main x 10 def f print x x x 1 g f if name main main 带有消息 Traceback most re
  • Typescript:如何在依赖项中返回正确的类和泛型类型

    我试图找到一种方法将一个对象注入另一个对象 依赖注入 其中容器对象可以返回正确注射对象类型 使用重载怎么样 function createMyClass2

随机推荐

  • Jquery UI 可排序 - 在启动事件触发之前执行操作

    我已经在 STACKOVERFLOW 和其他论坛中搜索了我的问题的解决方案 如果我错过了可行的解决方案 请指出它 我的问题 每当在可排序列表中拖动元素 Portlet div 时 我需要在实际拖动过程开始之前执行一些操作 根据我在 STAR
  • 如何在 Tkinter 中禁用(灰显)检查按钮?

    我不知道如何使 Tkinter 变灰Checkbutton 我尝试使用state DISABLED但它不起作用 我收到一条错误消息 tkinter TclError 错误选项 enable 必须是 column columnspan in
  • 如何访问父/兄弟模块方法

    有什么办法可以访问吗baz method inside class Qux没有从一开始就提到模块名称空间 当有很多嵌套模块时 代码看起来不干净 module Foo module Bar module Baz class Qux def s
  • Angular 2 - 使用 ng2-idle 注销

    我的问题是 当单击注销按钮时 ng2 idle 继续工作 为了尝试解决这个问题 我再次将 setIdle 和 setTimeout 函数设置为 1 秒 但是 当用户转移到登录屏幕时 应用程序需要 1 秒才能超时 我想知道在单击调用 logo
  • 如何在 Eclipse 中进行 git merge 压缩

    有时我需要从 Eclipse 合并南瓜 我知道我可以在命令行中完成此操作 但是在 Eclipse 中集成图形选项将非常有用 你知道该怎么做吗 您可以开始一个Egit 中的交互式变基 http wiki eclipse org EGit Us
  • 是否有可靠的工具可以在担任领班时单步执行代码

    我正在寻找一些关于类似于使用 binding pry 的工具的建议 我正在与 foreman 一起在本地提供 Rails 应用程序 并且希望实现相同的功能 将 调试器 放入我的代码中 当进程遇到该问题时 冻结并打开该代码部分中的控制台环境
  • 在 ASP.NET Core MVC 中使用 Tag Helpers 有什么好处

    我刚刚看到一篇关于 ASP NET Core 新功能的好文章 名为标签助手 http stephenwalther com archive 2015 02 24 top 10 changes in asp net 5 and mvc 6 从
  • 挂在 bootstrap 表中的 1000 或 5000 条记录上

    下面的链接给出了很好的例子 http issues wenzhixin net cn bootstrap table 但是 当分页大小从 10 更改为 1000 或 5000 时 浏览器会挂起超过 20 秒或一分钟才能填充网格 数据中的记录
  • 通过绑定新数据来操作元素

    我正在尝试弄清楚如何通过绑定新数据来更新一些 D3 js 元素 我实际上不确定这是否可能 但感觉应该是 首先我创建了四个 SVG 圆圈 并设置cx偏移量作为数据的函数 div div var svg d3 select div contai
  • 固定标题和固定列表

    我的固定标题和固定列表有问题 标题是固定的 但列不是 那么我该如何解决这个问题呢 我试图给第一列位置 固定 但它不能正常工作 如果可能的话 不用Javascript 我试图从同一主题的早期问题中找到解决方案 但这些都没有帮助我 这是我的Co
  • 如何以编程方式清除 Android 中的 DataStore 首选项和房间数据 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在开发一个 Android 应用程序 当我按下按钮时 我需要以编程方式清除数据 包括数据存储首选项和房间数据 要清除共享首选项 Sha
  • 以显式意图启动 Android IntentService NullPointerException

    我正在尝试开始一个IntentService来自我主要活动中的点击处理程序 我正在学习Intents现在但还不太明白 我不确定我应该如何在这里实例化我的意图并将其传递给startService 我不知道为什么我必须做这样的事Intent据我
  • Flutter改变FloatingActionButton的子图标颜色

    我是新来的Flutter并试图更改 FloatingActionButton 的子图标颜色 子图标颜色默认为白色 我怎样才能改变它 下面给出的是我已经编写的代码 floatingActionButton new FloatingAction
  • 如何在java中从像素字节数组制作bmp图像

    我有一个字节数组 其中包含 bmp 文件中的像素值 它是通过这样做生成的 BufferedImage readImage ImageIO read new File fileName byte imageData DataBufferByt
  • 需要一种方法在 MAUI 的编辑器/输入字段中隐藏软键盘

    我发现此链接中似乎有用的内容 Xamarin Forms 中的键盘禁用了 Entry 控件 https theconfuzedsourcecode wordpress com 2017 05 19 a keyboard disabled e
  • 在spark(2.4及更高版本)中,如何完全“编辑”所有敏感信息

    在 py spark 2 4 中 可以从事件日志中编辑一些敏感信息 例如 config spark eventLog enabled true config spark eventLog dir hdfs tmp spark events
  • snort make 文件给出错误

    我在创建 snort makefile 时收到此错误消息 usr bin ld usr local lib libpcre a pcre compile o 制作共享对象时不能使用针对 gt rodata 的重定位 R X86 64 32S
  • 如何从 .usdz 创建 SCNNode?

    我已经下载了Apple提供的 usdz模型 https developer apple com arkit gallery https developer apple com arkit gallery 但现在 我想使用这些模型之一创建一个
  • 在 iOS 11 PDFKit 文档上实现墨迹注释

    我想允许用户在 PDFView 中查看的 iOS 11 PDFKit 文档上绘图 绘图最终应嵌入到 PDF 中 我通过向 PDFPage 添加 ink 类型的 PDFAnnotation 以及与用户绘图相对应的 UIBezierPath 来
  • 如何创建一个 Ninject 自定义作用域,在该对象被释放之前返回相同的对象?

    在 Ninject 中 在单例范围内声明绑定意味着每次都会返回相同的对象 永远只能有一个对象 我想要的是一次返回一个对象 换句话说 第一次调用 Get 实例化一个新对象并返回它 对 Get 的后续调用返回相同的实例 该对象已被处置 对象被释