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

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介:

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
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号 蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
|
20天前
|
数据采集 安全 数据管理
深度解析:DataHub的数据集成与管理策略
【10月更文挑战第23天】DataHub 是阿里云推出的一款数据集成与管理平台,旨在帮助企业高效地处理和管理多源异构数据。作为一名已经有一定 DataHub 使用经验的技术人员,我深知其在数据集成与管理方面的强大功能。本文将从个人的角度出发,深入探讨 DataHub 的核心技术、工作原理,以及如何实现多源异构数据的高效集成、数据清洗与转换、数据权限管理和安全控制措施。通过具体的案例分析,展示 DataHub 在解决复杂数据管理问题上的优势。
85 1
|
17天前
|
安全 测试技术 数据安全/隐私保护
原生鸿蒙应用市场开发者服务的技术解析:从集成到应用发布的完整体验
原生鸿蒙应用市场开发者服务的技术解析:从集成到应用发布的完整体验
|
3月前
|
持续交付 jenkins Devops
WPF与DevOps的完美邂逅:从Jenkins配置到自动化部署,全流程解析持续集成与持续交付的最佳实践
【8月更文挑战第31天】WPF与DevOps的结合开启了软件生命周期管理的新篇章。通过Jenkins等CI/CD工具,实现从代码提交到自动构建、测试及部署的全流程自动化。本文详细介绍了如何配置Jenkins来管理WPF项目的构建任务,确保每次代码提交都能触发自动化流程,提升开发效率和代码质量。这一方法不仅简化了开发流程,还加强了团队协作,是WPF开发者拥抱DevOps文化的理想指南。
82 1
|
2月前
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
150 0
|
3月前
|
持续交付 jenkins C#
“WPF与DevOps深度融合:从Jenkins配置到自动化部署全流程解析,助你实现持续集成与持续交付的无缝衔接”
【8月更文挑战第31天】本文详细介绍如何在Windows Presentation Foundation(WPF)项目中应用DevOps实践,实现自动化部署与持续集成。通过具体代码示例和步骤指导,介绍选择Jenkins作为CI/CD工具,结合Git进行源码管理,配置构建任务、触发器、环境、构建步骤、测试及部署等环节,显著提升开发效率和代码质量。
76 0
|
3月前
|
存储 C# 关系型数据库
“云端融合:WPF应用无缝对接Azure与AWS——从Blob存储到RDS数据库,全面解析跨平台云服务集成的最佳实践”
【8月更文挑战第31天】本文探讨了如何将Windows Presentation Foundation(WPF)应用与Microsoft Azure和Amazon Web Services(AWS)两大主流云平台无缝集成。通过具体示例代码展示了如何利用Azure Blob Storage存储非结构化数据、Azure Cosmos DB进行分布式数据库操作;同时介绍了如何借助Amazon S3实现大规模数据存储及通过Amazon RDS简化数据库管理。这不仅提升了WPF应用的可扩展性和可用性,还降低了基础设施成本。
82 0
|
3月前
|
存储 开发者 C#
WPF与邮件发送:教你如何在Windows Presentation Foundation应用中无缝集成电子邮件功能——从界面设计到代码实现,全面解析邮件发送的每一个细节密武器!
【8月更文挑战第31天】本文探讨了如何在Windows Presentation Foundation(WPF)应用中集成电子邮件发送功能,详细介绍了从创建WPF项目到设计用户界面的全过程,并通过具体示例代码展示了如何使用`System.Net.Mail`命名空间中的`SmtpClient`和`MailMessage`类来实现邮件发送逻辑。文章还强调了安全性和错误处理的重要性,提供了实用的异常捕获代码片段,旨在帮助WPF开发者更好地掌握邮件发送技术,提升应用程序的功能性与用户体验。
58 0
|
3月前
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
159 0
|
3月前
|
开发者 算法 虚拟化
惊爆!Uno Platform 调试与性能分析终极攻略,从工具运用到代码优化,带你攻克开发难题成就完美应用
【8月更文挑战第31天】在 Uno Platform 中,调试可通过 Visual Studio 设置断点和逐步执行代码实现,同时浏览器开发者工具有助于 Web 版本调试。性能分析则利用 Visual Studio 的性能分析器检查 CPU 和内存使用情况,还可通过记录时间戳进行简单分析。优化性能涉及代码逻辑优化、资源管理和用户界面简化,综合利用平台提供的工具和技术,确保应用高效稳定运行。
83 0
|
3月前
|
机器学习/深度学习 TensorFlow 算法框架/工具
全面解析TensorFlow Lite:从模型转换到Android应用集成,教你如何在移动设备上轻松部署轻量级机器学习模型,实现高效本地推理
【8月更文挑战第31天】本文通过技术综述介绍了如何使用TensorFlow Lite将机器学习模型部署至移动设备。从创建、训练模型开始,详细演示了模型向TensorFlow Lite格式的转换过程,并指导如何在Android应用中集成该模型以实现预测功能,突显了TensorFlow Lite在资源受限环境中的优势及灵活性。
228 0

推荐镜像

更多