就我个人来说,当遇到一种新东西需要学习时,第一个想法就是找个例子来看看、改改。希望下面的这些讨论,对那些和我有着同样思路并且也正在看AspectSharp的朋友们有些帮助。
从官方网站上看到的AspectSharp的配置的结构是下面这样的:
首先,从资料和我的经验可以得出下面的结论:AspectSharp配置中的所有实体(包括Interceptor,Mixin,Class,Interface……)都可以使用Namespace.Name [in AssemblyName]的形式,比如ASTest.Interceptors.MyInterceptor in AssemblyASTest。
下面就对配置中的各个部门进行详细的说明。
Imports部分语法如下:
引入命名空间,类似于C#中using语句的作用。
参数:
<namespace>:命名空间的名称。
Global Interceptor Map部分语法如下:
声明Interceptor的别名,声明后的别名可以在当前配置文件中使用。
参数:
<key1>,<key2>:Interceptor的别名。
<interceptor1>,<interceptor2>:Interceptor的名称。
Global Mixin Map部分语法如下:
声明Mixin的别名,声明后的别名可以在当前配置文件中使用,类似Global Interceptor Map部分。
参数:
<key1>,<key2>:Mixin的别名。
<mixin1>,<mixin2>:Mixin的名称。
Aspects Definitions部分语法如下:
定义一个Aspect,用于识别一个类或一些类,并且进而识别类中的方法(属性)。如果对Aspect的概念不是很清楚的话,可以参考一些AOP方面的文献。
参数:
<name>:此Aspect的名称,似乎用处不大。
Aspects definitions中的Type部分语法如下:
定义当前Aspect所要识别的类型(类或接口)。可以使用三种形式中的任一种:
直接使用一个类名,用于识别一个类。
一个包括在中括号中的命名空间名,用于识别此命名空间下的所有类。
用于识别实现了一个接口的所有类,例子如[assignablefrom(IASTestInterface)]。
注意,在前两种形式中,只有类中的虚拟(Virtual)方法才能被进一步拦截,具体原因应该是来自于动态代理技术的限制。
参数:
<class>:类的名称。
<namespace>:命名空间的名称。
<interface>:接口的名称。
Aspects definitions中的Include部分语法如下:
在Aspect中定义向生成的代理中所引入的Mixin。
参数:
<mixin>:Mixin的名称或别名。
Aspects definitions中的pointcuts部分语法如下:
在Aspect中定义Pointcut。
参数:
<target>:识别的目标类型,仅包括4种:method,property,propertyread,propertywrite。其中可使用或操作符(|)连接多个目标类型。
<signature>:所识别的方法(或属性)的签名,其中可以使用通配符(*表示任意的类型或方法(或属性),.*表示方法名(或属性名)中的任意多个字母)。例如:
*可表示任何方法(或属性)。
Perform可表示返回任何类型的名为Perform的方法(或属性)。
int Perform(int) 可表示返回int类型并且传入一个int类型参数的方法。
P.*m可表示第一个字母为P最后一个字母为m的任何方法(或属性)。
Perform(string, *)可表示任何第一个参数为string类型并且名为Perform的方法(或属性)。
<interceptor>:Interceptor的名称或别名
注意:在AspectSharp中,当定义Pointcut时,似乎对void类型的方法不支持,如果必须要识别void方法,就只能使用*作为返回值了。
两个AspectSharp配置的具体例子:
例子一:
例子二:
从官方网站上看到的AspectSharp的配置的结构是下面这样的:
[Imports]
[Global Interceptor Map]
[Global Mixin Map]
Aspects Definitions
[Global Interceptor Map]
[Global Mixin Map]
Aspects Definitions
首先,从资料和我的经验可以得出下面的结论:AspectSharp配置中的所有实体(包括Interceptor,Mixin,Class,Interface……)都可以使用Namespace.Name [in AssemblyName]的形式,比如ASTest.Interceptors.MyInterceptor in AssemblyASTest。
下面就对配置中的各个部门进行详细的说明。
Imports部分语法如下:
import <namespace>
用途与说明:引入命名空间,类似于C#中using语句的作用。
参数:
<namespace>:命名空间的名称。
Global Interceptor Map部分语法如下:
interceptors [
"<key1>": <interceptor1>;
"<key2>": <interceptor2>
]
用途与说明:"<key1>": <interceptor1>;
"<key2>": <interceptor2>
]
声明Interceptor的别名,声明后的别名可以在当前配置文件中使用。
参数:
<key1>,<key2>:Interceptor的别名。
<interceptor1>,<interceptor2>:Interceptor的名称。
Global Mixin Map部分语法如下:
mixins [
"key1": <mixin1>;
"key2": <mixin2>
]
用途与说明:"key1": <mixin1>;
"key2": <mixin2>
]
声明Mixin的别名,声明后的别名可以在当前配置文件中使用,类似Global Interceptor Map部分。
参数:
<key1>,<key2>:Mixin的别名。
<mixin1>,<mixin2>:Mixin的名称。
Aspects Definitions部分语法如下:
aspect <name> for [Type]
[include]
[pointcuts]
end
用途与说明:[include]
[pointcuts]
end
定义一个Aspect,用于识别一个类或一些类,并且进而识别类中的方法(属性)。如果对Aspect的概念不是很清楚的话,可以参考一些AOP方面的文献。
参数:
<name>:此Aspect的名称,似乎用处不大。
Aspects definitions中的Type部分语法如下:
<class>
或[<namespace>]
或[assignablefrom(<interface>)]
用途与说明:定义当前Aspect所要识别的类型(类或接口)。可以使用三种形式中的任一种:
直接使用一个类名,用于识别一个类。
一个包括在中括号中的命名空间名,用于识别此命名空间下的所有类。
用于识别实现了一个接口的所有类,例子如[assignablefrom(IASTestInterface)]。
注意,在前两种形式中,只有类中的虚拟(Virtual)方法才能被进一步拦截,具体原因应该是来自于动态代理技术的限制。
参数:
<class>:类的名称。
<namespace>:命名空间的名称。
<interface>:接口的名称。
Aspects definitions中的Include部分语法如下:
include <mixin>
用途与说明:在Aspect中定义向生成的代理中所引入的Mixin。
参数:
<mixin>:Mixin的名称或别名。
Aspects definitions中的pointcuts部分语法如下:
pointcut <target> (<signature>)
advice(<interceptor>)
end
用途与说明:advice(<interceptor>)
end
在Aspect中定义Pointcut。
参数:
<target>:识别的目标类型,仅包括4种:method,property,propertyread,propertywrite。其中可使用或操作符(|)连接多个目标类型。
<signature>:所识别的方法(或属性)的签名,其中可以使用通配符(*表示任意的类型或方法(或属性),.*表示方法名(或属性名)中的任意多个字母)。例如:
*可表示任何方法(或属性)。
Perform可表示返回任何类型的名为Perform的方法(或属性)。
int Perform(int) 可表示返回int类型并且传入一个int类型参数的方法。
P.*m可表示第一个字母为P最后一个字母为m的任何方法(或属性)。
Perform(string, *)可表示任何第一个参数为string类型并且名为Perform的方法(或属性)。
<interceptor>:Interceptor的名称或别名
注意:在AspectSharp中,当定义Pointcut时,似乎对void类型的方法不支持,如果必须要识别void方法,就只能使用*作为返回值了。
两个AspectSharp配置的具体例子:
例子一:
import ASTest in AssemblyASTest
import ASTest.Mixins in AssemblyASTest
import ASTest.Interceptors in AssemblyASTest
interceptors [
"inter1": MyTestInterceptor
]
mixins [
"mixin1": MyTestMixin
]
aspect test1 for TestClass
pointcut method(*)
include inter1
advice(inter1)
end
end
import ASTest.Mixins in AssemblyASTest
import ASTest.Interceptors in AssemblyASTest
interceptors [
"inter1": MyTestInterceptor
]
mixins [
"mixin1": MyTestMixin
]
aspect test1 for TestClass
pointcut method(*)
include inter1
advice(inter1)
end
end
例子二:
aspect test2 for [assignableFrom(ASTest.ITest in AssemblyASTest)]
pointcut method|property(* ShowMessage(int))
advice(ASTest.Interceptors.MyTestInterceptor in AssemblyASTest)
end
end
pointcut method|property(* ShowMessage(int))
advice(ASTest.Interceptors.MyTestInterceptor in AssemblyASTest)
end
end