与 StructureMap 4.6 瞬态生命周期的混淆

2024-03-15

我使用 StructureMap 4.6 作为我的 IoC 容器。我对其生命周期有点困惑。正如我在其文档中所读到的那样,Transient 将为每个容器创建一个对象实例。支持的生命周期 http://structuremap.github.io/object-lifecycle/supported-lifecycles/

我正在通过创建一个简单的控制台应用程序项目来检查此场景。我的代码如下:

程序.cs

class Program
{
    private static IContainer _Container;
    static void Main(string[] args)
    {
        _Container = Container.For<ConsoleRegistry>();

        var serv1 = _Container.GetInstance<IFileService>();
        Console.WriteLine($"Name: {_Container.Name}");
        Console.WriteLine(serv1.GetUniqueID());

        var serv2 = _Container.GetInstance<IFileService>();
        Console.WriteLine($"Name: {_Container.Name}");
        Console.WriteLine(serv2.GetUniqueID());

        Console.ReadKey();
    }
}

控制台注册表.cs

public class ConsoleRegistry : Registry
{
    public ConsoleRegistry()
    {
        Scan(_ =>
        {
            _.TheCallingAssembly();
            _.WithDefaultConventions();
        });
    }
}

IFileService.cs

public interface IFileService
{
    string Read(string path);

    void Write(string path, string content);

    bool FileExists(string path);

    string GetUniqueID();
}

文件服务.cs

public class FileService : IFileService
{
    private static int instanceCounter;
    private readonly int instanceId;

    public FileService()
    {
        this.instanceId = ++instanceCounter;
        Console.WriteLine("File Service is Created.");
    }

    public int UniqueID
    {
        get { return this.instanceId; }
    }

    public string GetUniqueID()
    {
        return UniqueID.ToString();
    }

    public string Read(string path)
    {
        return File.ReadAllText(path);
    }

    public void Write(string path, string content)
    {
        File.WriteAllText(path, content);
    }

    public bool FileExists(string path)
    {
        return File.Exists(path);
    }
}

当我运行该应用程序时,结果是:

我的问题是当我解决一个实例时IFileService,我期望得到一个实例FileService每个容器。但是,正如您所看到的,它给出了两个不同的实例。为什么会这样?


您对以下内容的理解文档 http://structuremap.github.io/object-lifecycle/supported-lifecycles/是不正确的。

  • 瞬态——默认生命周期。为每个逻辑请求创建一个新对象,以解析容器中的对象图。
  • Singleton——只会为该容器以及该容器创建的任何子容器或嵌套容器创建一个对象实例

您正在使用短暂的,这意味着你得到一个实例每次Resolve叫做.

但你所描述的行为是为了辛格尔顿,这意味着创建实例只是第一次Resolve叫做.

要获得您想要的行为,您必须将注册类型更改为辛格尔顿.

public class ConsoleRegistry : Registry
{
    public ConsoleRegistry()
    {
        Scan(_ =>
        {
            _.TheCallingAssembly();
            _.With(new SingletonConvention<IFileService>());
            _.WithDefaultConventions();
        });
    }
}

internal class SingletonConvention<TPluginFamily> : IRegistrationConvention
{
    public void Process(Type type, Registry registry)
    {
        if (!type.IsConcrete() || !type.CanBeCreated() || !type.AllInterfaces().Contains(typeof(TPluginFamily))) return;

        registry.For(typeof(TPluginFamily)).Singleton().Use(type);
    }
}

参考:如何将 Structuremap 配置为通过 Singleton 自动扫描 Assembly 和 Cache 中的类型? https://stackoverflow.com/q/977862

单例 VS 瞬态示例

思考这个问题最简单的方法是举一个例子without使用 DI 容器。

Services

这里我们有一个服务和一个应用服务。这里唯一真正的区别是应用程序服务旨在整个应用图.

public class Service
{
    public string Name { get; private set; } = Guid.NewGuid().ToString();
}

public class Application
{
    private readonly Service singleton;
    private readonly Service transient;

    public Application(Service singleton, Service transient)
    {
        this.singleton = singleton;
        this.transient = transient;
    }

    public Service Singleton { get { return singleton; } }
    public Service Transient { get { return transient; } }
}

容器

在我们的容器中,我们注册了 2 个实例Service,一个单例和一个瞬态。单例仅被实例化每个容器实例一次。瞬态被实例化每次Resolve叫做.

public class MyContainer
{
    private readonly Service singleton = new Service();

    public Application Resolve()
    {
        return new Application(
            singleton: this.singleton, 
            transient: new Service());
    }
}

Usage

在现实世界的应用程序中,只会有一个实例Application。然而,我们展示的是两个Application实例来证明服务注册为Singleton将是同一容器实例的同一实例。每次都会创建一个瞬态Resolve叫做。

class Program
{
    static void Main(string[] args)
    {
        var container = new MyContainer();

        var application1 = container.Resolve();
        var application2 = container.Resolve();


        Console.WriteLine($"application1.Transient.Name: {application1.Transient.Name}");
        Console.WriteLine($"application2.Transient.Name: {application2.Transient.Name}");
        Console.WriteLine();
        Console.WriteLine($"application1.Singleton.Name: {application1.Singleton.Name}");
        Console.WriteLine($"application2.Singleton.Name: {application2.Singleton.Name}");

        Console.ReadKey();
    }
}

Output

application1.Transient.Name:dc134d4d-75c8-4f6a-a1a5-367156506671 application2.Transient.Name:f3012ea2-4955-4cfa-8257-8e03a00b1e99

application1.Singleton.Name:86d06d7d-a611-4f57-be98-036464797a41 application2.Singleton.Name:86d06d7d-a611-4f57-be98-036464797a41

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

与 StructureMap 4.6 瞬态生命周期的混淆 的相关文章

  • WPF DataGrid 多选

    我读过几篇关于这个主题的文章 但很多都是来自 VS 或框架的早期版本 我想做的是从 dataGrid 中选择多行并将这些行返回到绑定的可观察集合中 我尝试创建一个属性 类型 并将其添加到可观察集合中 它适用于单个记录 但代码永远不会触发多个
  • BASIC 中的 C 语言中的 PeekInt、PokeInt、Peek、Poke 等效项

    我想知道该命令的等效项是什么Peek and Poke 基本和其他变体 用 C 语言 类似PeekInt PokeInt 整数 涉及内存条的东西 我知道在 C 语言中有很多方法可以做到这一点 我正在尝试将基本程序移植到 C 语言 这只是使用
  • 在模板类中声明模板友元类时出现编译器错误

    我一直在尝试实现我自己的链表类以用于教学目的 我在迭代器声明中指定了 List 类作为友元 但它似乎无法编译 这些是我使用过的 3 个类的接口 Node h define null Node
  • C# 异步等待澄清?

    我读了here http blog stephencleary com 2012 02 async and await html that 等待检查等待的看看它是否有already完全的 如果 可等待已经完成 那么该方法将继续 运行 同步
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • 对类 static constexpr 结构的未定义引用,g++ 与 clang

    这是我的代码 a cp p struct int2 int x y struct Foo static constexpr int bar1 1 static constexpr int2 bar2 1 2 int foo1 return
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • 结构体的内存大小不同?

    为什么第一种情况不是12 测试环境 最新版本的 gcc 和 clang 64 位 Linux struct desc int parts int nr sizeof desc Output 16 struct desc int parts
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • x:将 ViewModel 方法绑定到 DataTemplate 内的事件

    我基本上问同样的问题这个人 https stackoverflow com questions 10752448 binding to viewmodels property from a template 但在较新的背景下x Bind V
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐

  • Django 中的条件登录重定向

    我知道关于LOGIN REDIRECT URL我知道
  • 如何以 CSV、C、Python、MatLab、NumPy 样式格式打印 cv::Mat

    我有一个 OpenCV 矩阵 我想以问题中提到的任何样式打印它 cv Mat1b image cv imread input name cv IMREAD GRAYSCALE std cout lt lt format in c style
  • Xna 绘制顺序无法正常工作

    我有一个 Texture2D 的二维数组 它在该数组中保存地图的不同部分 不过 我有一个问题 当我运行游戏时 地图绘制正确 但由于某种原因 数组 0 0 纹理重叠了我的所有纹理 包括我的玩家纹理和鼠标纹理 当我的鼠标和玩家纹理正确重叠地图时
  • 如何在 couchdb 中编写通配符搜索查询,其中名称如“a%”

    如何在 couchdb 中编写通配符搜索 我想在 sql 中编写与 LIKE 相同的查询 请帮助我 name arun surname mr name balu surname tp 我需要列出所有以 a 开头的名称 Thanks 在 co
  • 有关对齐的问题

    在函数内的局部作用域中声明时将所有相同类型的变量分组在一起是一个好习惯吗 如果是 为什么 它能解决内存对齐问题吗 我认为这对我 20 年前使用的 VAX C 编译器很重要 但对任何现代编译器都没有影响 这是not可以安全地假设局部变量将按任
  • 在 LISP 中实现基本库函数(手动)

    有什么方法可以定义函数my list my cons my append其执行类似的功能list cons and append分别 否则哪里可以找到这些功能的实现呢 Thanks 对于my list和my append 解决方案是 def
  • 在 Windows 上部署 QML 应用程序的正确方法

    最近 我需要为我的 Qt QML 应用程序创建一个部署包 这个过程非常繁琐 因为您需要手动查找并复制依赖项 正如 官方 中所述Qt Wiki https wiki qt io Deploy an Application on Windows
  • 如何将动态创建的文本字段值发送到 php 邮件

    input type radio click function val this val container html content val this attr count var i 1 for i 0 i lt val i conte
  • 可以在 Oracle 的 SELECT 中执行自动编号序列吗?

    我需要在 Oracle 中完成一项任务 但我不知道如何才能做到这一点 好的 当我动态定义自动编号序列时 我需要执行 SELECT 例如 Select autonumber 1 9000 as auto from some table 结果是
  • ng2-ckeditor 404(未找到)

    我使用 cmd npm install ng2 ckeditor 添加了 ng2 CKEDitor 安装得很好 有一个例子https www npmjs com package ng2 ckeditor https www npmjs co
  • 无法使用 psycopg2 连接到 Postgres 容器

    我有以下设置 容器中的一个简单 Flask 应用程序 Postgres 容器 使用以下 Dockerfile FROM python alpine3 7 COPY app WORKDIR app RUN apk update RUN apk
  • Eclipse 调试配置中的默认 VM 参数?

    当我使用 TDD 实现新功能时 我经常使用快捷方式Shift Alt D T仅运行我当前正在处理的 jUnit 测试用例 而不是整个测试套件 这需要几分钟 这将为当前 Java 源创建一个新的调试配置并立即运行它 现在我想在启用断言的情况下
  • AutoCompleteTextView 未完成括号内的单词

    我已经实施了AutoCompleteTextView如下 MainActivity java public static String myData new String Africa AF America AFM Apple AMP te
  • 将自定义数据嵌入到不会被 ld.so 映射的 ELF 文件中

    我有一个 500MB 的文件 其中包含一些自定义数据 即 ZIP 存档 我想将它嵌入到我的 ELF 可执行文件中 这样当我分发 ELF 文件时 我将只能发送 1 个文件而不是 2 个文件 问题是我不希望在我的应用程序启动时操作系统自动加载这
  • 在 Entity Framework 4.0 中批处理 DB 命令

    我当前的项目需要每天与外部系统同步 同步基于复杂的导入文件结构 该结构通过广泛的业务逻辑进行解析和处理 由于业务逻辑的原因 我们决定在 NET 代码中进行此操作并重用现有的 BL 组件 而不是在存储过程或集成服务中编写相同的逻辑 BL 层位
  • .Net 中的单元测试属性?

    我正在开发一个我想以开源方式发布的库 我已经开始为代码编写测试 我想知道如何测试 Net 对象中的属性 可以说我有以下内容 public class Person region variables private string name S
  • 生成三角/六角坐标 (xyz)

    我试图提出一个迭代函数来生成六角形网格的 xyz 坐标 使用起始六边形位置 为简单起见 假设为 0 0 0 我想计算每个连续的六边形 环 的坐标 如下所示 到目前为止 我所能想到的就是这个 javascript 中的示例 var radiu
  • 具有 AsynchronousServerSocketChannel 的多线程服务器

    我必须实现一个应该接受更多连接的服务器 没有任何更深入的思考 我决定使用新的 JAVA NIO 2 类 我目前的做法是 final Semaphore wait new Semaphore 1 while true wait acquire
  • 为什么函数绑定到它们传递的第一个类型

    我是 F 新手 我在闲逛 发现了一些有趣的东西 我希望有人能启发我了解幕后发生的事情 所以我做了这个功能 let my func x y x y 然后我用参数调用该函数1 and 2给我3 这是我期望发生的事情 但是当我将两个字符串传递给m
  • 与 StructureMap 4.6 瞬态生命周期的混淆

    我使用 StructureMap 4 6 作为我的 IoC 容器 我对其生命周期有点困惑 正如我在其文档中所读到的那样 Transient 将为每个容器创建一个对象实例 支持的生命周期 http structuremap github io