Microsoft NLayerApp案例理论与实践 - 基础结构层(Cross-Cutting部分)
NLayerApp中IoC容器的实现在应用程序设计的过程中我们会基于这样一个设计准则就是类型之间的关联应该依赖于接口或者抽象而非具体的实现。这样就使得我们能够在保证整个程序结构不变的情况下很方便地替换组件的具体实现方式这不仅使得Service Stub模式的应用成为可能从而提高了系统的可测试性而且解耦了组件之间的依赖关系降低了应用程序的维护成本。IoC容器是这样一种对象它在应用程序的执行环境中维护着接口与其实现之间的映射关系以及各个实现对象之间的依赖关系以便当客户程序向IoC容器提出请求时能够返回与所请求的接口或抽象类型所对应的具体实现客户程序不需要去关心返回的具体实现究竟是什么以及如何去初始化这个具体实现。本文不会对IoC作过多的介绍有兴趣的朋友可以阅读《Inversion of Control Containers and the Dependency Injection pattern》这篇文章。NLayerApp中IoC容器的实现依赖于Microsoft PatternsPractices Unity其实大多数应用程序甚至是开发框架都会依赖于第三方的类库来实现IoC容器因为IoC本身涉及的内容就比较多很好地解决类型之间复杂的依赖关系也不是一件很容易的事情。Unity并非IoC的唯一选择除了Unity之外Spring.NET、Castle Windsor、Ninject、StructureMap等都可以成为IoC容器不错的选择。NLayerApp中与IoC容器实现有关的类及其之间的关系如下图所示在上图中IContainer接口定义了IoC容器相关的方法它是与具体的实现技术无关的接口接口的层次结构树、其中定义的方法的参数以及返回值等都不会依赖于任何第三方的组件因此理论上我们可以通过继承IContainer接口然后用我们自己的技术方式来实现IoC容器。NLayerApp是使用Unity作为IoC容器的因此上图的IoCUnityContainer类实现了IContainer接口然后在IoCFactory的单件实例中通过new关键字创建了IoCUnityContainer的实例12345678910#region Constructor/// summary/// Only for singleton pattern, remove before field init IL anotation/// /summarystaticIoCFactory() { }IoCFactory(){_CurrentContainer newIoCUnityContainer();}#endregion当然对于NLayerApp这一特定的应用程序案例而言这样做是没什么问题的但如果我们目前设计的是一个开发框架的话直接使用new关键字来创建IoCUnityContainer的实例就会使得IoCFactory强行依赖于IoCUnityContainer类型于是也就违背了“关联应该依赖于接口或者抽象而非具体实现”的设计准则。在最新版的Apworks框架的代码中开发人员可以通过应用程序的配置信息来选择合适的IoC容器比如你可以在应用程序启动的时候就决定是使用Unity还是Castle Windsor这就使得框架本身具有更好的扩展性。刚才我们也讨论过如果要使NLayerApp能够使用我们自定义的IoC容器就要继承IContainer接口那么现在我们还需要修改IoCFactory的私有构造函数以使用我们自己的IoC容器来初始化_CurrentContainer私有成员。Unity容器有一个非常实用的特点就是“根容器”与“子容器”的概念在“根容器”上通过调用CreateChildContainer方法即可创建与之关联的子容器。根容器和子容器都可以接受抽象类型的注册。每当客户程序向子容器请求类型Resolve Type时Unity首先检查子容器中是否有所请求的类型如果有则直接返回该类型的具体实现如果没有则会将该请求转发给其父容器。利用Unity的这种特性我们可以将针对不同部署环境的IoC容器进行统一管理比如将各种部署环境中相同的类型映射注册在根容器中然后为每个部署环境创建一个子容器将与部署环境相关的特定类型映射注册在各自的子容器中。下图展示了NLayerApp中Unity IoC容器的基本情况通过阅读IoCUnityContainer的源代码我们可以了解到在IoCUnityContainer的构造函数中创建了rootContainer并在rootContainer上使用CreateChildContainer创建了用于真实运行环境的realAppContainer以及用于单体测试的fakeAppContainer之后就是使用下面的私有方法逐个初始化这些容器12345678910111213141516171819202122232425262728293031/// summary/// Configure root container.Register types and life time managers for unity builder process/// /summary/// param namecontainerContainer to configure/paramvoidConfigureRootContainer(IUnityContainer container){// Omitted... Please refer to the source code for details.}/// summary/// Configure real container. Register types and life time managers for unity builder process/// /summary/// param namecontainerContainer to configure/paramvoidConfigureRealContainer(IUnityContainer container){container.RegisterTypeIMainModuleUnitOfWork, MainModuleUnitOfWork(newPerExecutionContextLifetimeManager(),newInjectionConstructor());}/// summary/// Configure fake container.Register types and life time managers for unity builder process/// /summary/// param namecontainerContainer to configure/paramvoidConfigureFakeContainer(IUnityContainer container){//Note: Generic register type method cannot be used here,//MainModuleFakeContext cannot have implicit conversion to IMainModuleContextcontainer.RegisterType(typeof(IMainModuleUnitOfWork),typeof(FakeMainModuleUnitOfWork),newPerExecutionContextLifetimeManager());}在ConfigureRootContainer方法中对所有环境真实运行环境以及单体测试环境需要用到的类型进行了注册然后就IMainModuleUnitOfWork而言由于真实运行环境和单体测试环境所使用的Unit Of Work具体实现不同真实运行环境使用的是MainModuleUnitOfWork实现而测试环境则是使用的FakeMainModuleUnitOfWork于是也就在ConfigureRealContainer和ConfigureFakeContainer方法中分别作了注册。最后每当IContainer.Resolve方法被调用时系统会通过读取配置文件来决定目前应该使用哪个容器来解析类型因此我们只需要在配置文件中正确设置容器的名称即可在NLayerApp中使用指定的Unity IoC容器。下面这段配置信息来自于DistributedServices.Deployment项目从中我们可以看到NLayerApp的Distributed Services使用的是realAppContainer123456appSettings!--RealAppContext - Real Container--!--FakeAppContext - Fake Container--!--add keydefaultIoCContainer valueFakeAppContext /--addkeydefaultIoCContainer valueRealAppContext //appSettingsNLayerApp中用于跟踪程序执行过程的Trace工具NLayerApp中Trace工具的实现非常简单在Infrastructure.CrossCutting项目中定义了ITraceManager然后在Infrastructure.CrossCutting.NetFramework项目中定义了ITraceManager的具体实现。TraceManager使用了System.Diagnostics命名空间下与Trace相关的类型实现其功能应用程序则通过IoCFactory来获得ITraceManager的具体实现。在上面讨论的ConfigureRootContainer方法中NLayerApp对ITraceManager类型进行了注册12//Register crosscuting mappingscontainer.RegisterTypeITraceManager, TraceManager(newTransientLifetimeManager());因此在整个应用程序中就可以使用下面的方式来获取ITraceManager的具体实现以便完成Trace功能12ITraceManager traceManager IoCFactory.Instance.CurrentContainer.ResolveITraceManager();traceManager.TraceError(/* error message*/);

相关新闻

E-Hentai漫画批量下载:3步解锁你的个人数字图书馆

E-Hentai漫画批量下载:3步解锁你的个人数字图书馆

E-Hentai漫画批量下载:3步解锁你的个人数字图书馆 你是否曾在深夜浏览E-Hentai时,发现心仪的漫画集却苦于无法一次性保存?或者因为网络不稳定而不得不反复刷新页面,只为下载那几张珍贵的图片?今天,让我带你…

2026/7/4 20:43:44 阅读更多 →
DWT硬件延时

DWT硬件延时

1、Cortex-M4内核架构2、硬件延时利用计数功能的硬件进行延时,比如单片机片上定时器(Timer),内核滴答定时器(systick)等:__weak void HAL_IncTick(void) {uwTick; } __weak uint32_t HAL_GetTick(void) {return uwTick…

2026/7/4 20:41:43 阅读更多 →
如何通过5个简单步骤实施HARA

如何通过5个简单步骤实施HARA

确保汽车系统的安全性并非易事。随着现代车辆日益复杂,识别并减轻潜在危险变得比以往任何时候都更加关键。这正是危害分析与风险评估(HARA)发挥作用的地方。 HARA是一种结构化方法,旨在评估风险并制定符合ISO 26262(汽…

2026/7/4 20:41:43 阅读更多 →

最新新闻

Obsidian-skills:为AI代理注入Obsidian超能力,开启智能知识管理新纪元

Obsidian-skills:为AI代理注入Obsidian超能力,开启智能知识管理新纪元

Obsidian-skills:为AI代理注入Obsidian超能力,开启智能知识管理新纪元 【免费下载链接】obsidian-skills Agent skills for Obsidian. Teach your agent to use Obsidian CLI and open formats including Markdown, Bases, JSON Canvas. 项目地址: htt…

2026/7/4 21:38:07 阅读更多 →
Touch WX开发常见问题解答:新手必看的避坑指南

Touch WX开发常见问题解答:新手必看的避坑指南

Touch WX开发常见问题解答:新手必看的避坑指南 【免费下载链接】touchwx 小程序组件化解决方案。官网:https://www.wetouch.net/wx.html 项目地址: https://gitcode.com/gh_mirrors/to/touchwx Touch WX是一套完全免费的微信小程序开发框架&#…

2026/7/4 21:34:04 阅读更多 →
Spectre在机构级量化交易中的应用:大规模数据处理实战案例

Spectre在机构级量化交易中的应用:大规模数据处理实战案例

Spectre在机构级量化交易中的应用:大规模数据处理实战案例 【免费下载链接】spectre GPU-accelerated Factors analysis library and Backtester 项目地址: https://gitcode.com/gh_mirrors/spe/spectre Spectre作为一款GPU加速的因子分析库和回测工具&#…

2026/7/4 21:34:04 阅读更多 →
BigFunctions快速入门:10分钟学会在BigQuery中调用公共函数

BigFunctions快速入门:10分钟学会在BigQuery中调用公共函数

BigFunctions快速入门:10分钟学会在BigQuery中调用公共函数 【免费下载链接】bigfunctions Supercharge BigQuery with BigFunctions 项目地址: https://gitcode.com/gh_mirrors/bi/bigfunctions 想要快速掌握BigFunctions的强大功能吗?这篇终极指…

2026/7/4 21:32:02 阅读更多 →
CANN/hccl代码示例集

CANN/hccl代码示例集

HCCL Code Examples 【免费下载链接】hccl 集合通信库(Huawei Collective Communication Library,简称HCCL)是基于昇腾AI处理器的高性能集合通信库,为计算集群提供高性能、高可靠的通信方案 项目地址: https://gitcode.com/cann…

2026/7/4 21:30:02 阅读更多 →
CANN/mat-chem-sim-pred PID阶跃响应特征算法

CANN/mat-chem-sim-pred PID阶跃响应特征算法

PidStepResponseFeatures Algorithm 【免费下载链接】mat-chem-sim-pred 面向工业领域,聚焦计算仿真、预测两大核心场景,构建面向流程工业"机理数据"双轮驱动的领域计算层,推动AI for Science在材料化学领域的深度应用。 项目地址…

2026/7/4 21:30:02 阅读更多 →

日新闻

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 正式发布,这是一个关键的安全修复版本,修复了多个方面的问题,还对部分功能进行了优化。 安全修复亮点 此次发布在安全修复上表现突出。binprot 避免了项目引用计数溢出,mcmc 因安全问题提升了上游版本号&#xf…

2026/7/4 0:04:29 阅读更多 →
终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案 【免费下载链接】HMCL A Minecraft Launcher which is multi-functional, cross-platform and popular 项目地址: https://gitcode.com/gh_mirrors/hm/HMCL HMCL(Hello Minecraft! Lau…

2026/7/4 0:06:29 阅读更多 →
KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

1. KMX63与PIC18F66K40的硬件协同架构解析KMX63作为一款三轴加速度计和磁力计组合传感器,与PIC18F66K40微控制器的搭配堪称嵌入式HMI开发的黄金组合。这套硬件组合的核心优势在于KMX63提供的高精度运动感知能力与PIC18F66K40强大的信号处理能力形成了完美互补。KMX6…

2026/7/4 0:06:29 阅读更多 →

周新闻

月新闻