Enterprise Library深入解析与灵活应用(1):通过Unity Extension实现和Policy Injection Application Block的集成

简介:

Enterprise Library是微软P&P部门开发的众多Open source框架中的一个,最新的版本已经出到了4.0。由于接触Enterprise Library已经有很长的一段时间,在实际的项目中使用的频率也很高。对此有了一些积累,希望通过这个新的系列和广大网友一起分享和交流。本系列假设读者已经对Enterprise Library有一定的了解,故而不会对各个Application Block的基本原理和编程模型进行介绍,而把侧重点放在Enterprise Library深层次的实现原理、设计模式的应用、有效扩展和最佳实践上。

 

今天我们讨论的内容是如何通过自定义UnityContainerExtension实现Unity和PIAB的集成,我们假设读者已经对Unity Application Block和Policy Injection Application Block已经有了一定的了解。

一、创建PolicyInjectionStrategy

我们知道Policy Injection Application Block是基于Remoting的原理通过Method Interception的方式实现了AOP(而另一种常见的方式是基于IL Injection)。要使应用在目标对象的CallHandler发挥作用,需用通过PolicyInjecctor(默认为Remoting PolicyInjection)进行对象的创建。而实现Unity和PIAB集成的途径就是让Unity Container使用进行对象的创建。

Unity是建立在ObjectBuilder之上的,而ObjectBuilder是整个Enterprise Library以及P&P其他开源框架(比如Smart Client Software Factory)的基石。ObjectBuilder,顾名思义,就是进行对象创建的组件。而ObjectBuilder进行对象创建的方式是基于策略的(Strategy based object creation),他通过将不同的策略运用到对象创建(或释放回收)的不同的阶段,而从提供了一个功能强大的、极具扩展的对象创建的框架。而要实现我们的目标,首先需要创建自定义的BuilderStrategy:PolicyInjectionStrategy 。

   1: namespace Artech.PolicyInjectionIntegratedInUnity
   2: {
   3:     public class PolicyInjectionStrategy : EnterpriseLibraryBuilderStrategy
   4:     {
   5:         public override void PreBuildUp(IBuilderContext context)
   6:         {
   7:             base.PreBuildUp(context);
   8:             if (context.Policies.Get<IPolicyInjectionPolicy>(context.BuildKey) == null)
   9:             {
  10:                 context.Policies.Set<IPolicyInjectionPolicy>(new PolicyInjectionPolicy(true), context.BuildKey);
  11:             }
  12:         } 
  13:  
  14:         public override void PostBuildUp(IBuilderContext context)
  15:         {
  16:             base.PostBuildUp(context);
  17:             IPolicyInjectionPolicy policy = context.Policies.Get<IPolicyInjectionPolicy>(context.BuildKey);
  18:             if ((policy != null) && policy.ApplyPolicies)
  19:             {
  20:                 policy.SetPolicyConfigurationSource(EnterpriseLibraryBuilderStrategy.GetConfigurationSource(context));
  21:                 context.Existing = policy.ApplyProxy(context.Existing, BuildKey.GetType(context.OriginalBuildKey));
  22:             }
  23:         }
  24:     }
  25: }
  26:  
  27:  

上面就是整个PolicyInjectionStrategy 的定义。通过PreBuildUp在对象创建之前将PolicyInjectionPolicy添加到BuilderContext 的Policy列表中(BuilderContext 为整个对象的创建和生命周期的管理提供context信息)。在PostBuildUp中,将PolicyInjectionPolicy从BuilderContext 中取出,调用ApplyProxy方法将创建的对象通过PolicyInjecctor进行封装,那么调用被封装过的对象,我们的Policy Injection CallHandler就可以发挥其作用了。

注:PolicyInjectionPolicy定了在Microsoft.Practices.EnterpriseLibrary.PolicyInjection dll中,实现了Microsoft.Practices.EnterpriseLibrary.PolicyInjection.ObjectBuilder.IPolicyInjectionPolicy和Microsoft.Practices.ObjectBuilder2.IBuilderPolicy。其ApplyProxy方法实际上就是调用了PolicyInjecctor的Wrap方法。

二、创建PolicyInjectionExtension

有了PolicyInjectionStrategy,我们自定义UnityContainerExtension就显得很简单了,需要做的仅仅是override Initialize方法,创建PolicyInjectionStrategy对象,并将其加入到当前BuilderContext 的Strategie列表中即可。

   1: namespace Artech.PolicyInjectionIntegratedInUnity
   2: {
   3:     public class PolicyInjectionExtension : UnityContainerExtension
   4:     {
   5:         protected override void Initialize()
   6:         {
   7:             base.Context.Strategies.AddNew<PolicyInjectionStrategy>(UnityBuildStage.Initialization);
   8:         }
   9:     }
  10: } 
  11:  

三、通过coding的方式应用PolicyInjectionExtension

我们现在将我们定义的PolicyInjectionExtension使用到实际的场景中,看看它能够像我们希望的那样,调用通过Unity container创建的对象上的方法,其对应的Policy Injection CallHandler能够被正常地执行。我们仍然使用CachingCallHandler和TimeService来做试验。为此,我定义了一个interface(ITimeService) 和他的实现(TimeService ),并通过cusotom attribute的方式在class上应用了CachingCallHandler。

   1: public interface ITimeService
   2: {
   3:         DateTime GetSystemTime();
   4: } 
   5:  
   6: [CachingCallHandler]
   7: public class TimeService : ITimeService
   8: {
   9:     #region IContract Members 
  10:  
  11:     public DateTime GetSystemTime()
  12:     {
  13:             return DateTime.Now;
  14:     } 
  15:  
  16:         #endregion
  17:     }
  18: } 
  19:  

在Console application的Main()中,先创建UnityContainer对象,然后通过AddExtension将我们定义的PolicyInjectionExtension添加到该UnityContainer种,然后进行interface和concrete type匹配关系的注册。最后通过Resolve方法创建ITimeService 对象,并在for循环中以一定的时间间隔(1s)调用GetSystemTime方法。

   1: namespace Artech.PolicyInjectionIntegratedInUnity
   2: {
   3:     class Program
   4:     {
   5:         static void Main(string[] args)
   6:         {
   7:                 IUnityContainer container = new UnityContainer();
   8:                 container.AddExtension(new PolicyInjectionExtension());
   9:                      container.RegisterType<ITimeService, TimeService>();
  10:                 ITimeService instance = container.Resolve<ITimeService>();
  11:                 for (int i = 0; i < 10; i++)
  12:                 {
  13:                     Console.WriteLine(instance.GetSystemTime());
  14:                     Thread.Sleep(1000);
  15:                 }
  16:             }        
  17:     }  
  18: } 
  19:  

因为我们在TimeService 使用了CachingCallHandler,GetSystemTime方法返回的结果将会被缓存。所以输出的时间都是相同的,如下图所示:

image

四、通过configuration的方式应用PolicyInjectionExtension

Unity的主要的目的是实现了DI(dependency injection). DI的目的说白了还是实现松耦合。而送耦合实现的一个主要的途径还是将编译时的依赖转换成运行时的依赖。所以在很多情况下只用通过配置的方式才能真正意义上实现解耦。而Unity的大多数使用场景还是基于configuration方式的。为了实现上一节中通过coding一样的功能,我们定义了如下的Unity配置:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <configuration>
   3:     <configSections>
   4:         <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
   5:     </configSections>   
   6:     <unity>
   7:         <containers>
   8:             <container>
   9:                 <types>
  10:                    <type type="Artech.PolicyInjectionIntegratedInUnity.ITimeService,Artech.PolicyInjectionIntegratedInUnity" mapTo="Artech.PolicyInjectionIntegratedInUnity.TimeService,Artech.PolicyInjectionIntegratedInUnity"/>
  11:                 </types>
  12:                 <extensions>
  13:                     <add type="Artech.PolicyInjectionIntegratedInUnity.PolicyInjectionExtension,Artech.PolicyInjectionIntegratedInUnity" />
  14:                 </extensions>
  15:             </container>
  16:         </containers>
  17:     </unity>
  18: </configuration> 
  19:  

我们通过配置的方式实现了type的注册和extension的添加。有了上面的配置,我们的code进行相应的改动使用unity的配置:

   1: namespace Artech.PolicyInjectionIntegratedInUnity
   2: {
   3:     class Program
   4:     {
   5:         static void Main(string[] args)
   6:         {
   7:             IUnityContainer container = new UnityContainer();
   8:             UnityConfigurationSection unityConfigSection = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
   9:             unityConfigSection.Containers.Default.Configure(container);
  10:             ITimeService instance = container.Resolve<ITimeService>();
  11:             for (int i = 0; i < 10; i++)
  12:             {
  13:                 Console.WriteLine(instance.GetSystemTime());
  14:                 Thread.Sleep(1000);
  15:             }
  16:         }
  17:     } 
  18: } 
  19:  

运行上面的代码,我们一样可以得到相同的输出:

image

 

 

 

 

 

 


 

Enterprise Library深入解析与灵活应用:
[1] 通过Unity Extension实现和Policy Injection Application Block的集成
[2] 通过SqlDependency实现Cache和Database的同步
[3] 倘若将Unity、PIAB、Exception Handling引入MVP模式
[4] 创建一个自定义Exception Handler改变ELAB的异常处理机制
[5] 创建一个简易版的批处理执行器,认识Enterprise Library典型的配置方式和对象创建方式
[6] 自己动手创建迷你版AOP框架
[7] 再谈PIAB与Unity之间的集成



作者:蒋金楠
微信公众账号:大内老A
微博: www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号 蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
|
数据采集 安全 数据管理
深度解析:DataHub的数据集成与管理策略
【10月更文挑战第23天】DataHub 是阿里云推出的一款数据集成与管理平台,旨在帮助企业高效地处理和管理多源异构数据。作为一名已经有一定 DataHub 使用经验的技术人员,我深知其在数据集成与管理方面的强大功能。本文将从个人的角度出发,深入探讨 DataHub 的核心技术、工作原理,以及如何实现多源异构数据的高效集成、数据清洗与转换、数据权限管理和安全控制措施。通过具体的案例分析,展示 DataHub 在解决复杂数据管理问题上的优势。
1481 1
|
人工智能 自然语言处理 Java
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
FastExcel 是一款基于 Java 的高性能 Excel 处理工具,专注于优化大规模数据处理,提供简洁易用的 API 和流式操作能力,支持从 EasyExcel 无缝迁移。
3377 65
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
|
10月前
|
Java 开发工具 Spring
【Azure Application Insights】为Spring Boot应用集成Application Insight SDK
本文以Java Spring Boot项目为例,详细说明如何集成Azure Application Insights SDK以收集和展示日志。内容包括三步配置:1) 在`pom.xml`中添加依赖项`applicationinsights-runtime-attach`和`applicationinsights-core`;2) 在main函数中调用`ApplicationInsights.attach()`;3) 配置`applicationinsights.json`文件。同时提供问题排查建议及自定义日志方法示例,帮助用户顺利集成并使用Application Insights服务。
290 8
|
机器学习/深度学习 人工智能 自然语言处理
企业级API集成方案:基于阿里云函数计算调用DeepSeek全解析
DeepSeek R1 是一款先进的大规模深度学习模型,专为自然语言处理等复杂任务设计。它具备高效的架构、强大的泛化能力和优化的参数管理,适用于文本生成、智能问答、代码生成和数据分析等领域。阿里云平台提供了高性能计算资源、合规与数据安全、低延迟覆盖和成本效益等优势,支持用户便捷部署和调用 DeepSeek R1 模型,确保快速响应和稳定服务。通过阿里云百炼模型服务,用户可以轻松体验满血版 DeepSeek R1,并享受免费试用和灵活的API调用方式。
719 12
|
机器学习/深度学习 自然语言处理 监控
智能客服系统集成技术解析和价值点梳理
在 2024 年的智能客服系统领域,合力亿捷等服务商凭借其卓越的技术实力引领潮流,它们均积极应用最新的大模型技术,推动智能客服的进步。
613 7
|
安全 测试技术 数据安全/隐私保护
原生鸿蒙应用市场开发者服务的技术解析:从集成到应用发布的完整体验
原生鸿蒙应用市场开发者服务的技术解析:从集成到应用发布的完整体验
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
1130 1
|
持续交付 jenkins Devops
WPF与DevOps的完美邂逅:从Jenkins配置到自动化部署,全流程解析持续集成与持续交付的最佳实践
【8月更文挑战第31天】WPF与DevOps的结合开启了软件生命周期管理的新篇章。通过Jenkins等CI/CD工具,实现从代码提交到自动构建、测试及部署的全流程自动化。本文详细介绍了如何配置Jenkins来管理WPF项目的构建任务,确保每次代码提交都能触发自动化流程,提升开发效率和代码质量。这一方法不仅简化了开发流程,还加强了团队协作,是WPF开发者拥抱DevOps文化的理想指南。
335 1
|
域名解析 网络协议 API
【API管理 APIM】APIM集成内部VNet时,常遇见的关于自定义DNS服务问题。
【API管理 APIM】APIM集成内部VNet时,常遇见的关于自定义DNS服务问题。
203 4
|
JSON 数据管理 关系型数据库
【Dataphin V3.9】颠覆你的数据管理体验!API数据源接入与集成优化,如何让企业轻松驾驭海量异构数据,实现数据价值最大化?全面解析、实战案例、专业指导,带你解锁数据整合新技能!
【8月更文挑战第15天】随着大数据技术的发展,企业对数据处理的需求不断增长。Dataphin V3.9 版本提供更灵活的数据源接入和高效 API 集成能力,支持 MySQL、Oracle、Hive 等多种数据源,增强 RESTful 和 SOAP API 支持,简化外部数据服务集成。例如,可轻松从 RESTful API 获取销售数据并存储分析。此外,Dataphin V3.9 还提供数据同步工具和丰富的数据治理功能,确保数据质量和一致性,助力企业最大化数据价值。
625 1

推荐镜像

更多
  • DNS