WPF的MVVM框架Stylet开发文档 14.7-14.9 杂项、性能、技术

2023-11-10

14.7 StyletIoC 杂项

文档地址

此页面包含其他各种值得一提的点点滴滴,但还不够大,不值得单独放置一个页面。

循环依赖

循环依赖项(下面记录的类型除外)会导致 StackOverflow 异常。提前发现这些问题并非易事,虽然 StackOverflow 异常并不理想,但不值得避免它的复杂性。

父/子循环依赖

假设你有这样的事情:

class Parent
{
   public Parent(Child child) { ... }
}

class Child
{
   public Parent Parent { get; set; }
}

您希望 StyletIoC 能够在其中创建 Parent 或 Child 的实例,并适当地创建另一个实例。

诀窍是使用工厂来创建两者,而不是使用容器来解析 Child 的实例并创建 Parent,反之亦然。这有点乱,但是无论如何循环依赖都是乱七八糟的。

Child 的 Parent 属性不能_有_属性[Inject],否则该BuildUp步骤将导致 StackOverflow。

builder.Bind<Parent>().ToFactory(container =>
{
   var child = new Child();
   container.BuildUp(child); // 如果child需要进行属性注入,则进行构建
   var parent = new Parent(child);
   child.Parent = parent;
   return parent; // parent将由 StyletIoC 自动建立
});
builder.Bind<Child>().ToFactory(container =>
{
   var child = new Child();
   var parent = new Parent(child);
   container.BuildUp(parent); // 如果parent需要进行属性注入,则进行构建
   child.Parent = parent;
   return child; // child将由 StyletIoC 自动建立
});

14.8 StyletIoC 性能

文档地址

很难比较不同 IoC 容器的性能。增加的复杂性通常会以性能为代价,因此功能更多的包含几乎总是会变慢。

然而,这些数字看起来非常有趣,所以这里是 Munq 的基准测试,修改后添加了 StyletIoC。

Running 500000 iterations for each use case.
                          Test:        Ticks -         mSec -   Normalized
              No IOC Container:      153,169 -        92.47 -         1.00
                     StyletIoC:      418,840 -       252.86 -         2.73
                          Munq:    3,009,272 -     1,816.74 -        19.65
                         Unity:   48,533,016 -    29,300.02 -       316.86
                       Autofac:   69,065,954 -    41,696.02 -       450.91
                  StructureMap:   15,356,998 -     9,271.22 -       100.26
                      Ninject2:  269,115,738 -   162,468.69 -     1,756.99
                       Windsor:  191,559,858 -   115,647.19 -     1,250.64
              StyletIoCFactory:    3,082,670 -     1,861.05 -        20.13
                   MunqFactory:    2,777,705 -     1,676.94 -        18.13
                AutofacFactory:   18,526,411 -    11,184.64 -       120.95
           StructureMapFactory:   15,708,059 -     9,483.16 -       102.55
               Ninject2Factory:  197,354,786 -   119,145.67 -     1,288.48
    No IOC Container Singleton:       27,382 -        16.53 -         0.18
            StyletIoCSingleton:      183,638 -       110.86 -         1.20
                 MunqSingleton:      411,133 -       248.21 -         2.68
                UnitySingleton:    8,048,317 -     4,858.87 -        52.55
              AutofacSingleton:    3,205,066 -     1,934.94 -        20.93
         StructureMapSingleton:    5,007,675 -     3,023.20 -        32.69
             Ninject2Singleton:   30,795,175 -    18,591.45 -       201.05
              WindsorSingleton:    2,379,411 -     1,436.48 -        15.53
                          Hiro:      252,305 -       152.32 -         1.65

在顶部没有后缀的条目中,容器负责确定如何实例化该类型,例如 builder.Bind<ISomeType>().To<SomeType>()。以 ‘Factory’ 结尾的条目是通过使用 builder.Bind<ISomeType>().To(container => new SomeType(container.Get<ISomeDependency>())) 进行绑定创建的,而以 ‘Singleton’ 结尾的条目是容器配置为始终为每个类型返回相同的实例。

一个有趣的观察是,StyletIoC 并不比简单地实例化类型慢多少——事实上,StyletIoC 实际上实例化类型的速度与本机代码一样快,它正在确定要实例化的类型,这会增加额外的。

另一个是,在 Factory 和 Singleton 情况下,StyletIoC 的速度与 Munq 几乎相同。然而,当容器负责确定如何实例化类型本身的实例时,StyletIoC 的速度要快一个数量级以上。这要感谢对 C# 表达式的一些巧妙使用,这在StyletIoC Technical中有所介绍。

14.9 StyletIoC 技术

文档地址

此页面是为想要深入研究 StyletIoC 源代码以验证它或提交拉取请求的人准备的背景阅读材料。

表达式:如何快速实例化一个类型

在运行时创建类型实例的传统方法是使用 Activator.CreateInstance,例如 Activator.CreateInstance(instanceType, new object[] { container.Get(param1Type), container.Get(param2Type) })。然而,这样做速度非常慢,大多数 IoC 容器不再使用它(如果它们曾经使用过)。

C# 3 引入了表达式树,C# 4 对其进行了扩展。表达式树可以用于生成指定某些操作(例如 a + b)的表达式,并在运行时将其编译为 IL 作为委托。这允许您使用例如 Expression.New(intanceType) 编写表达式,并将其编译为与手动编写 new Instance() 一样快的委托。

许多 IoC 容器采用了这种方法,并使用它来编写表达式,描述代码中的 Instance(container.Get(param1Type), container.Get(param2Type))。这比 Activator.CreateInstance 快得多,但仍需要为每个要解析的参数访问 IoC 容器,从而产生额外的开销。

StyletIoC 更进一步,生成描述 new Instance(new Param1Instance(), new Param2Instance()) 的代码表达式,这样做速度更快。

当其中一个参数需要属性注入时,也会使用此技巧,创建一个等效于以下内容的表达式:

var param1 = new Param1Instance();
param1.SomeProperty = new SomePropertyInstance();
new Instance(param1, new Param2Instance());

创作者和注册

StyletIoC 主要围绕着两个重要接口展开:ICreatorIRegistration

ICreator 知道如何提供一个类型的实例 - TypeCreator 知道如何创建一个类型的实例(如果你使用 Bind<..>().To<...>() 注册一个类型,就会使用它),而 FactoryCreator 则知道如何使用你指定的工厂创建一个实例(使用 Bind<..>().ToFactory(...))。

IRegistration 负责实例的生命周期,会在需要时使用它拥有的 ICreator 创建类型的新实例。TransientRegistration 每次都会创建一个新实例,而 SingletonRegistration 只会调用它的 ICreator 一次,并缓存结果实例。大多数情况下都使用 TransientRegistration,但如果你使用 .InSingletonScope() 指定一个单例,则会使用 SingletonRegistration

还有一个更复杂的部分,就是 IRegistrationCollection,它由 SingleRegistration(拥有单个 IRegistration)和 RegistrationCollection(拥有一组 IRegistration)实现。这主要是为了优化 - IRegistrationCollection 可以被要求提供一个单独的 IRegistration,也可以提供多个,而 RegistrationCollection 会在前者的情况下引发异常。

在 StyletIoC 的核心是一个字典,它的键是 [serviceType,key],值是 IRegistrationCollection。当你调用 IContainer.Get 时,StyletIoC 会找到正确的 IRegistrationCollection,并向它请求单个 IRegistration。然后,它将要求该 IRegistration 提供其类型的实例。

GetAll 注册

当请求注册项的集合时,情况会稍微复杂一些。StyletIoC还有一个字典,其键为 [elementType,key],值为 IRegistration,其中该 IRegistrationGetAllRegistration。给定一个 IEnumerable<T>,您可以提取 T,然后使用它从此字典中获取一个 IRegistration。该 IRegistration 可以创建一个包含所有正确元素的 List<T>

该字典由 IContainer.GetAll 和负责构造函数和属性注入的代码的部分使用,当它们遇到 IEnumerable<T> 时。

当需要时,此字典将即时填充。

未绑定的泛型

当您注册一个未绑定泛型类型时(例如 builder.Bind(typeof(IValidator<>)).To(typeof(Validator<>))),StyletIoC会将一个条目添加到 [未绑定泛型类型, key] => List<UnboundGeneric> 字典中。如果您请求的泛型类型不在注册字典中,StyletIoC会查看是否可以使用此字典中的任何条目构造该类型。如果可以,它将创建一个新的 IRegistration,并将其添加到注册字典中。

BuilderUppers

另外有一个字典也是解决方案的一部分,它是type => BuilderUpper。每个BuilderUpper都知道如何在该类型的实例上执行属性注入。当您调用IContainer.BuildUp时,会查询此字典,检索相关的BuilderUpper(如果它不存在则创建),并用于构建您的类型。它也被ICreator用于执行属性注入。

项目原地址:https://github.com/canton7/Stylet

上一节:WPF的MVVM框架Stylet开发文档 14.6 StyletIoC 模块

上一篇:WPF的MVVM框架Stylet开发文档 13.验证模型基类 ValidatingModelBase
下一篇:WPF的MVVM框架Stylet开发文档 15. 视图管理器 The ViewManager

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

WPF的MVVM框架Stylet开发文档 14.7-14.9 杂项、性能、技术 的相关文章

随机推荐

  • 《Thinking in Java》读后总结与感想

    作为Java界的四大名著之一 Thinking in Java 一直备受推崇 我很早就知道了这本书 当时只是初涉Java 粗略的翻了翻之后觉得看起来这本书讲的比较深就没有再去碰它 后来Java基础学完之后又忙着学Android开发的知识 就
  • 如何打开mysql_MySQL教程

    MySQL经常和 数据库 连在一起读 这很容易对新手造成误解 认为MySQL就是一个数据库 其实不是这样 MySQL是数据库的集合 MySQL里面有很多数据库 那么数据是直接存在数据库里的吗 并不 数据库底下还有一个叫做数据表的存储单元 数
  • 无需公网IP,安全访问云端资源,3步搞定

    某企业将OA ERP Git代码库等业务资源 分别部署在了公有云和私有云 但随着业务发展 分部和移动办公人员逐渐增多 如何高效实现50名员工安全远程访问云端资源成了难题 使用MPLS专线 IPSec VPN等传统方案实现远程访问 不仅实施费
  • Spring的入门及案例----Ioc

    一 Spring的核心 Spring的核心是控制反转 IoC 和面向切面 AOP 简单来说 Spring是一个分层的JavaSE EEfull stack 一站式 轻量级开源框架 IoC 控制反转 对于Spring来说 Spring创建对象
  • 通过css内修改input框placeholder样式

    使用css内修改input框placeholder样式 需求将input框内placeholder属性文字设置颜色及字体大小 修改前 修改后 代码 input webkit input placeholder WebKit Blink Ed
  • 利用std::async实现异步功能

    c 11标准推出了多线程功能 其中我比较喜欢的是把async和future联合起来使用 实现异步功能 目录 首先介绍async的使用办法 输入参数 返回值 std future的使用办法 异步结果的获取 等待异步结果的返回 wait wai
  • Android图像开源视图:SmartImageView

    项目需要 开发中需要加载图片 自己要写图片从网上下载的方法 还要写缓存 等等 在网上找到一个开源项目 smartImageVIew 支持从URL和通讯录中获取图像 可以替代Android标准的ImageView 特征 根据URL地址装载图像
  • C# ---Constructor, Object Initializer, Property, Constant, and readonly

    C Constructor Object Initializer Property Constant and Readonly Constructor and Object Initializer Fields and Property 如
  • queue使用方法

    queue使用方法 提示 如果队列满了 那么使用put放入数据会等待 直到队列有空闲位置才可以放入 放入消息的时候不会进行等待 如果发现队列满了不能放入数据 那么会直接崩溃 import multiprocessing import tim
  • Spring Boot使用@Async实现异步调用

    1 Spring Boot使用 Async实现异步调用 链接 link 原文 http blog csdn net a286352250 article details 53157822 项目GitHub地址 https github co
  • 大数据背景下如何加强高校财务管理水平

    1 建立软 硬件平台 智能的软件平台是大数据技术实施的主要依托 必须加强与大数 据相适应的平台建设 才能充分发挥大数据技术的优势 服务好高校 财务管理工作 云平台存储便捷 处理高效 管理智能 是与大数据技术适应的 最佳软件平台 因此 高校要
  • python宽度学习训练后模型的持久化存储和快速调用

    在模型训练完成后 我们需要对我们训练出来的模型进行持久性储存 这样既能将我们调参后得到的最佳模型进行存储 还可以方便后期同团队的人进行调用预测 1 原理 此处用到的是sklearn库中的joblib包进行存储和加载 因为宽度学习的类属于自定
  • 华为OD机考-构建输入和输出

    华为OD机考 ACM模式下创建输入 概述 下文列举机考过程中常见输入的构造方法 如字符串 多维数组等 并对用到的函数进行详细讲解 最后通过真题实操巩固知识点 一 机考中常见的输入 1 输入字符串 输入一行字符串 str1 input pri
  • 36 数据增广 [动手学深度学习v2]

    数据增强 增加一个已有数据集 使得有更多的多样性 在语言里面加入各种不同的背景噪音 改变图片的颜色和形状 图像增广 import torch import torchvision from torch import nn 左右翻转图像 to
  • 深度学习刷 SOTA 有哪些 trick?

    深度学习刷 SOTA 有哪些 trick 此问题在知乎上有超 1700 人关注 浏览量超 32 万 相信是大家都非常关心的问题 快一起看看下面的分享吧 希望可以帮助到大家 对于图像分类任务 让我们以 Swin Transformer 中使用
  • 【2023】基于docker 实现部署jar包项目(包括单个和多个一起部署)

    建议学习本博客之前 需要对docke的基本命令有过学习 目录 前言 1 项目打包 2 编写Dockerfile文件 2 1 单个jar部署 Dockerfile文件常用命令 2 2 1 编写一个Dockerfile 文件格式制作镜像 2 1
  • AngularJs的生命周期

    AngularJs的生命周期分为六个阶段 编译 AngularJs会遍历浏览器提供的dom树 尝试参照已注册的指令集来匹配每个元素 属性 注释和css类 每当匹配一个指令时 ag就会调用该指令的编译函数 该函数返回一个连接函数 ag会收集所
  • linux 命令行操作串口

    linux 命令行操作串口 1 获取串口号 2 配置串口属性 stty命令 3 串口数据读写操作 4 解析数据 5 后台运行 6 绘制数据 Linux stty命令 一 参数 二 用法 Linux下minicom操作 Linux minic
  • 算法第六题:压缩字符串 2021-08-21

    一 题目 给你一个字符数组 chars 请使用下述算法压缩 从一个空字符串 s 开始 对于 chars 中的每组 连续重复字符 如果这一组长度为 1 则将字符追加到 s 中 否则 需要向 s 追加字符 后跟这一组的长度 压缩后得到的字符串
  • WPF的MVVM框架Stylet开发文档 14.7-14.9 杂项、性能、技术

    14 7 StyletIoC 杂项 文档地址 此页面包含其他各种值得一提的点点滴滴 但还不够大 不值得单独放置一个页面 循环依赖 循环依赖项 下面记录的类型除外 会导致 StackOverflow 异常 提前发现这些问题并非易事 虽然 St