博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Unity Behaviors for Interception
阅读量:5172 次
发布时间:2019-06-13

本文共 5802 字,大约阅读时间需要 19 分钟。

Unity提供了自带的拦截器,如果你并不想编写繁琐的拦截器可以选择编写更轻量的方式Behavior。拦截器的应用场景有不少,比如一些数据访问框架,它们的核心概念是AOP。通过创建一个继承于类型的代理类型,并重写它的virtual函数将拦截器置入其中。前置处理函数负责打开数据库连接、启动事务,后置处理器负责提交事务、关闭数据库连接。Unity的VirtualMethodInterceptor就可以帮助我们完成这个功能。

如果你熟悉WPF/Silverlight,那么一定了解这两年流行的MVVM。WPF/Silverlight的数据绑定基于DataContext类型是一个DependencyObject还是一个实现了INotifyPropertyChanged接口的类型。当绑定类型的属性发生改变,数据绑定机制会主动将变化更新到UI。由于所有ViewModel都需要实现INotifyPropertyChanged接口,并且需要在每个属性的setter上显示的产生属性变化的通知:

 

1 public class MainViewModel : INotifyPropertyChanged 2 { 3   private String m_name; 4  5   public MainViewModel() { } 6  7   public virtual String Name 8   { 9     get { return m_name; }10     set11     {12       if (!String.Equals(m_name, value))13       {14         m_name = value;15 16         OnPropertyChanged(“Name”);17       }18     }19   }20 21   private void OnPropertyChanged(String propertyName)22   {23     PropertyChangedEventHandler handler = PropertyChanged;24 25     if (handler != null)26       handler(this, new PropertyChangedEventArgs(propertyName));27   }28 29   #region INotifyPropertyChanged Members30 31   public event PropertyChangedEventHandler PropertyChanged;32 33   #endregion34 }

上面的视图模型可以优化,创建一个ViewModelBase的基类,实现了INotifyPropertyChanged接口,并提供了OnPropertyChanged函数。但对于ViewModel的开发人员来说仍旧需要在各处添加触发PropertyChanged事件的函数或代码。我们可以通过Unity的VirtualMethodInterceptor,编写一个NotifyPropertyChangedBehavior实现属性变化的通知。看一个示例:

1 //   2 /// 属性变化行为  3 ///   4 public sealed class NotifyPropertyChangedBehavior : IInterceptionBehavior  5 {  6   ///   7   /// 添加事件函数信息  8   ///   9   private static readonly MethodInfo AddEventMethodInfo = typeof(INotifyPropertyChanged).GetEvent(“PropertyChanged”).GetAddMethod(); 11  12   ///  13   /// 删除事件函数信息 14   ///  15   private static readonly MethodInfo RemoveEventMethodInfo = typeof(INotifyPropertyChanged).GetEvent(“PropertyChanged”).GetRemoveMethod(); 17  18   ///  19   /// 属性变化事件 20   ///  21   private event PropertyChangedEventHandler PropertyChanged; 22  23   ///  24   /// 构造函数 25   ///  26   public NotifyPropertyChangedBehavior() { } 27  28   ///  29   /// 是否为属性Setter 30   ///  31   /// 输入 32   /// 
为属性Setter
33   private static Boolean IsPropertySetter(IMethodInvocation input) 34   { 35     return input.MethodBase.IsSpecialName && input.MethodBase.Name.StartsWith(“set_”); 36   } 37 38   /// 39   /// 添加事件订阅 40   /// 41   /// 输入 42   /// 下一个行为 43   ///
函数返回值
44   private IMethodReturn AddEventSubscription(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 45   { 46     var subscriber = (PropertyChangedEventHandler)input.Arguments[0]; 47 48     this.PropertyChanged += subscriber; 49 50     return input.CreateMethodReturn(null); 51   } 52 53   /// 54   /// 删除事件订阅 55   /// 56   /// 输入 57   /// 下一个行为 58   ///
函数返回值
59   private IMethodReturn RemoveEventSubscription(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 60   { 61     var subscriber = (PropertyChangedEventHandler)input.Arguments[0]; 62 63     this.PropertyChanged -= subscriber; 64 65     return input.CreateMethodReturn(null); 66   } 67 68   /// 69   /// 拦截属性设置 70   /// 71   /// 输入 72   /// 下一个行为 73   ///
函数返回值
74   private IMethodReturn InterceptPropertySet(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 75   { 76     var propertyName = input.MethodBase.Name.Substring(4); 77     var returnValue = getNext()(input, getNext); 78     var subscribers = PropertyChanged; 79 80     if (subscribers != null) 81       subscribers(input.Target, new PropertyChangedEventArgs(propertyName)); 82 83     return returnValue; 84   } 85 86   #region IInterceptionBehavior Members 87 88   /// 89   /// 是否将执行 90   /// 91   public Boolean WillExecute 92   { 93     get { return true; } 94   } 95 96   /// 97   /// 获得需要的接口遍历器 98   /// 99   ///
接口遍历器
100   public IEnumerable
GetRequiredInterfaces()101   {102     return new[] { typeof(INotifyPropertyChanged) };103   }104 105   ///
106   /// 调用107   /// 108   ///
输入109   ///
下一个行为110   ///
函数返回值
111   public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)112   {113     // 如果为添加事件114     if (input.MethodBase == AddEventMethodInfo)115       return AddEventSubscription(input, getNext);116 117     // 如果为删除事件118     if (input.MethodBase == RemoveEventMethodInfo)119       return RemoveEventSubscription(input, getNext);120 121     // 设置属性122     if (IsPropertySetter(input))123       return InterceptPropertySet(input, getNext);124 125     return getNext()(input, getNext);126   }127 128   #endregion129 }130 131 public class MainViewModel132 {133   public MainViewModel() { }134 135   public virtual String Name { get; set; }136 }137 138 IUnityContainer unityContainer = new UnityContainer();139 140 unityContainer.AddNewExtension
();141 unityContainer.RegisterType
(new Interceptor
(), new InterceptionBehavior(new NotifyPropertyChangedBehavior()));142 143 MainViewModel viewModel = unityContainer.Resolve
();144 145 ((INotifyPropertyChanged)viewModel).PropertyChanged += new PropertyChangedEventHandler((sender, e) => Console.WriteLine(e.PropertyName));146 147 viewModel.Name = “hello, world”;

上面的示例可以看到MainViewModel被附加了PropertyChanged行为,开发人员不再需要为视图模型的属性变化编写大量重复的代码。一个拦截行为需要实现IInterceptionBehavior的三个定义:WillExecute属性、GetRequiredInterfaces函数、Invoke函数。

WillExecute:定义当前行为是否将被执行,开发人员可以根据不同情况编写相应逻辑。

GetRequiredInterfaces:返回需要被附加的接口,比如MainViewModel并没有实现INotifyPropertyChanged,但是被拦截后创建的代理类型被附加了INotifyPropertyChanged接口。

Invoke:拦截后的真正调用,getNext是下一个行为,整个行为附加是一个链式调用。

转载于:https://www.cnblogs.com/junchu25/archive/2012/08/10/2631577.html

你可能感兴趣的文章
JS实现密码加密
查看>>
卓越年华家具有限公司介绍
查看>>
2016-03-30
查看>>
Python的语言类型
查看>>
l-oc-9
查看>>
angular.js (五)
查看>>
【转】网络制图法(Internet Cartography)
查看>>
Oracle网络TNS协议的几个基础类描述(revised)
查看>>
shell编程笔记
查看>>
Winform打砖块游戏制作step by step第三节---移动挡板
查看>>
hdu3999-The order of a Tree (二叉树的先序遍历)...
查看>>
corona物理引擎中物体有粘性的解决办法
查看>>
LA 6979 Known Notation 构造+贪心 铜牌题
查看>>
Linux MTD下获取Nand flash各个参数的过程的详细解析【转】
查看>>
Gson使用
查看>>
Integrate Your Code with the Frameworks---整合你的代码和框架
查看>>
欧拉回路和欧拉路径
查看>>
Java 推荐读物与源代码阅读
查看>>
BlogEngine.Net架构与源代码分析系列part1:开篇介绍
查看>>
N皇后问题
查看>>