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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 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
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号 蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
|
1月前
|
数据采集 安全 数据管理
深度解析:DataHub的数据集成与管理策略
【10月更文挑战第23天】DataHub 是阿里云推出的一款数据集成与管理平台,旨在帮助企业高效地处理和管理多源异构数据。作为一名已经有一定 DataHub 使用经验的技术人员,我深知其在数据集成与管理方面的强大功能。本文将从个人的角度出发,深入探讨 DataHub 的核心技术、工作原理,以及如何实现多源异构数据的高效集成、数据清洗与转换、数据权限管理和安全控制措施。通过具体的案例分析,展示 DataHub 在解决复杂数据管理问题上的优势。
266 1
|
16天前
|
机器学习/深度学习 自然语言处理 监控
智能客服系统集成技术解析和价值点梳理
在 2024 年的智能客服系统领域,合力亿捷等服务商凭借其卓越的技术实力引领潮流,它们均积极应用最新的大模型技术,推动智能客服的进步。
50 7
|
1月前
|
安全 测试技术 数据安全/隐私保护
原生鸿蒙应用市场开发者服务的技术解析:从集成到应用发布的完整体验
原生鸿蒙应用市场开发者服务的技术解析:从集成到应用发布的完整体验
|
4月前
|
图形学 C#
超实用!深度解析Unity引擎,手把手教你从零开始构建精美的2D平面冒险游戏,涵盖资源导入、角色控制与动画、碰撞检测等核心技巧,打造沉浸式游戏体验完全指南
【8月更文挑战第31天】本文是 Unity 2D 游戏开发的全面指南,手把手教你从零开始构建精美的平面冒险游戏。首先,通过 Unity Hub 创建 2D 项目并导入游戏资源。接着,编写 `PlayerController` 脚本来实现角色移动,并添加动画以增强视觉效果。最后,通过 Collider 2D 组件实现碰撞检测等游戏机制。每一步均展示 Unity 在 2D 游戏开发中的强大功能。
223 6
|
3月前
|
设计模式 存储 人工智能
深度解析Unity游戏开发:从零构建可扩展与可维护的游戏架构,让你的游戏项目在模块化设计、脚本对象运用及状态模式处理中焕发新生,实现高效迭代与团队协作的完美平衡之路
【9月更文挑战第1天】游戏开发中的架构设计是项目成功的关键。良好的架构能提升开发效率并确保项目的长期可维护性和可扩展性。在使用Unity引擎时,合理的架构尤为重要。本文探讨了如何在Unity中实现可扩展且易维护的游戏架构,包括模块化设计、使用脚本对象管理数据、应用设计模式(如状态模式)及采用MVC/MVVM架构模式。通过这些方法,可以显著提高开发效率和游戏质量。例如,模块化设计将游戏拆分为独立模块。
220 3
|
3月前
|
vr&ar 图形学 API
Unity与VR控制器交互全解:从基础配置到力反馈应用,多角度提升虚拟现实游戏的真实感与沉浸体验大揭秘
【8月更文挑战第31天】虚拟现实(VR)技术迅猛发展,Unity作为主流游戏开发引擎,支持多种VR硬件并提供丰富的API,尤其在VR控制器交互设计上具备高度灵活性。本文详细介绍了如何在Unity中配置VR支持、设置控制器、实现按钮交互及力反馈,结合碰撞检测和物理引擎提升真实感,助力开发者创造沉浸式体验。
194 0
|
3月前
|
图形学 开发者
透视与正交之外的奇妙视界:深入解析Unity游戏开发中的相机与视角控制艺术,探索打造沉浸式玩家体验的奥秘与技巧
【8月更文挑战第31天】在Unity中,相机不仅是玩家观察游戏世界的窗口,更是塑造氛围和引导注意力的关键工具。通过灵活运用相机系统,开发者能大幅提升游戏的艺术表现力和沉浸感。本文将探讨如何实现多种相机控制,包括第三人称跟随和第一人称视角,并提供实用代码示例。
169 0
|
3月前
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
160 0
|
3月前
|
图形学 开发者 UED
Unity游戏开发必备技巧:深度解析事件系统运用之道,从生命周期回调到自定义事件,打造高效逻辑与流畅交互的全方位指南
【8月更文挑战第31天】在游戏开发中,事件系统是连接游戏逻辑与用户交互的关键。Unity提供了多种机制处理事件,如MonoBehaviour生命周期回调、事件系统组件及自定义事件。本文介绍如何有效利用这些机制,包括创建自定义事件和使用Unity内置事件系统提升游戏体验。通过合理安排代码执行时机,如在Awake、Start等方法中初始化组件,以及使用委托和事件处理复杂逻辑,可以使游戏更加高效且逻辑清晰。掌握这些技巧有助于开发者更好地应对游戏开发挑战。
160 0
|
4月前
|
开发者 图形学 API
从零起步,深度揭秘:运用Unity引擎及网络编程技术,一步步搭建属于你的实时多人在线对战游戏平台——详尽指南与实战代码解析,带你轻松掌握网络化游戏开发的核心要领与最佳实践路径
【8月更文挑战第31天】构建实时多人对战平台是技术与创意的结合。本文使用成熟的Unity游戏开发引擎,从零开始指导读者搭建简单的实时对战平台。内容涵盖网络架构设计、Unity网络API应用及客户端与服务器通信。首先,创建新项目并选择适合多人游戏的模板,使用推荐的网络传输层。接着,定义基本玩法,如2D多人射击游戏,创建角色预制件并添加Rigidbody2D组件。然后,引入网络身份组件以同步对象状态。通过示例代码展示玩家控制逻辑,包括移动和发射子弹功能。最后,设置服务器端逻辑,处理客户端连接和断开。本文帮助读者掌握构建Unity多人对战平台的核心知识,为进一步开发打下基础。
154 0

推荐镜像

更多
下一篇
DataWorks