惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

雷峰网
雷峰网
宝玉的分享
宝玉的分享
I
InfoQ
P
Privacy International News Feed
V
V2EX
IT之家
IT之家
S
SegmentFault 最新的问题
D
Darknet – Hacking Tools, Hacker News & Cyber Security
V2EX - 技术
V2EX - 技术
C
CERT Recently Published Vulnerability Notes
C
Check Point Blog
The Register - Security
The Register - Security
爱范儿
爱范儿
博客园 - 三生石上(FineUI控件)
AWS News Blog
AWS News Blog
M
MIT News - Artificial intelligence
C
Cyber Attacks, Cyber Crime and Cyber Security
F
Fortinet All Blogs
B
Blog
N
Netflix TechBlog - Medium
B
Blog RSS Feed
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Last Week in AI
Last Week in AI
T
Threatpost
Forbes - Security
Forbes - Security
U
Unit 42
A
Arctic Wolf
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
P
Palo Alto Networks Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Recorded Future
Recorded Future
L
Lohrmann on Cybersecurity
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Proofpoint News Feed
月光博客
月光博客
Spread Privacy
Spread Privacy
MongoDB | Blog
MongoDB | Blog
Jina AI
Jina AI
I
Intezer
V
Visual Studio Blog
阮一峰的网络日志
阮一峰的网络日志
The Hacker News
The Hacker News
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
L
LangChain Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园_首页
MyScale Blog
MyScale Blog
腾讯CDC
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
量子位

博客园 - williambirkin

今天看PolicyInjection遇到的问题 我的第一个ASP.NET Ajax控件 转 事务隔离级别 转 UML 基础: 类图 关于Form.show的问题 关于where中子查询的性能问题 请高手指教 模式 转 SQL Server 索引结构及其使用 (三) 转 SQL Server 索引结构及其使用 (二) 转 SQL Server 索引结构及其使用 (一) 泛型的一点思考 摘自《.NET 2.0 模式开发实战》 转 《为Windows应用创建简单的异步调用模式》 转 C#格式化数值结果表(格式化字符串) SQL游标的简单使用 转“理解VC# 2005中的字符串和正规表达式” 2个IP输入控件 Windows Forms中禁用窗体的关闭按钮 回车移动焦点 文本框事件顺序
.NET平台自带的AOP机制 转自《设计模式--基于c#的工程化实现及扩展》
williambirkin · 2010-03-23 · via 博客园 - williambirkin

本文实例选自《设计模式--基于c#的工程化实现及扩展》

原文的目的是通过.NET对AOP机制的原生支持实现Decorator模式。

基础原理(摘自Artech 的 Enterprise Library Policy Injection Application Block 之二: PIAB设计和实现原理):

MBRObjRefRealProxyTransparentProxy,对于这些名词,我想熟悉或者接触过.NET Remoting的人肯定不会不陌生。由于PIAB的实现机制依赖于Remoting的这种Marshaling,如果对此不了解的读者将对后面的介绍很难理解,所以很有必要先做以下简单的介绍。

我们知道,CLR通过AppDomain实现不同Application之间的隔离,在通常情况下,不同AppDomain不同共享内存。在一个AppDomain中创建的对象不能直接被运行在另一个AppDomain的程序使用。跨AppDomain对象的共享依赖于一个重要的过程:Marshaling。我们有两种不同的Marshaling方式:Marshaling by ValueMarshaling by Reference。前者采用的是Serialization/Deserialization的方式,而后者则是采用传递Reference的方式来实现,其实现原来如下:

Remoting Infrastructure先生成对象的ObjRef InstanceObjRefSystem.Runtime.Remoting.ObjRef)代表远程对象的一个Reference,存储着跨AppDomain远程调用所需的所有的信息,比如URI、类型的层次结构、以及实现的Interface等等。ObjRef是可以序列化的,也就是说它可以按照by Value的方式进行Marshaling。所以可以这么说Marshaling by Reference依赖对对ObjRefMarshaling by Value

ObjRef产地到另一个AppDomain的实现,将根据ObjRef的数据生成两个Proxy对象:RealProxyTransparentProxyRealProxy根据ObjRef创建,通过RealProxy创建TransparentProxy。当进行远程调用的时候,Client直接和TransparentProxy打交道,对TransparentProxy的调用将会ForwardRealProxyRealProxy通过Remoting InfrastructureCommunicateActivation机制将Invocate传递给被激活的Remote Object

MBR通常在一个跨AppDomain的环境下实现远程调用,但是这种机制在用一个AppDomian依然有效,而且可以免去跨AppDomain的性能损失。PIAB就是充分运用了这种在同一个AppDomain下的MBR

下面这个简单AOP 的例子也是使用了以上思想。通过在RealProxy中增加对目标方法调用的拦截。然后将调用的处理权交由目标方法上的标签类进行处理。在标签类处理完各种检验后RealProxy再执行对目标方法的调用。

代码如下:

定义装饰标签的基类

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)]
public abstract class DecoratorAttributeBase : Attribute
{
public abstract void Intercept(object target);
}

定义代理类

 
      /// <summary>
  
/// 实际代理对象
   /// </summary>
public class CustomProxy<T> : RealProxy, IDisposable where T : MarshalByRefObject
{
/// <summary>
/// 构造过程中把Proxy需要操作的内容与实际目标对象实例Attach到一起
/// </summary>
/// <param name="target"></param>
public CustomProxy(T target):base(target.GetType())
{
AttachServer(target);
}
#region IDisposable 成员
/// <summary>
/// 析构过程则借助Proxy和目标对象实例的Attach,便于GC回收
/// </summary>
public void Dispose()
{
DetachServer();
}
#endregion/// <summary>
/// 创建目标实例的transparent代理对象
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
public static T Create(T target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
return (T)(new CustomProxy<T>(target).GetTransparentProxy());
}
public override IMessage Invoke(IMessage msg)
{
MethodCallMessageWrapper caller
= new MethodCallMessageWrapper((IMethodCallMessage)msg);//提取实际宿主对象
MethodInfo method = (MethodInfo)caller.MethodBase;

T target

= (T)GetUnwrappedServer();

DecoratorAttributeBase[] attributes

=
(DecoratorAttributeBase[])method.GetCustomAttributes(
typeof(DecoratorAttributeBase), true);if (attributes.Length > 0)
{
foreach (DecoratorAttributeBase attribute in attributes)
{
attribute.Intercept(caller);
}
}
object ret = method.Invoke(target,caller.Args);return new ReturnMessage(ret, caller.Args, caller.ArgCount, caller.LogicalCallContext, caller);

}
}

定义具体装饰属性

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class ArgumentNotEmptyAttribute : DecoratorAttributeBase
{
public override void Intercept(object target)
{
MethodCallMessageWrapper caller
= new MethodCallMessageWrapper((IMethodCallMessage)target);if (caller.ArgCount == 0)
{
return;
}
foreach (object arg in caller.Args)
{
if ((string.IsNullOrEmpty((string)arg)))
{
throw new ArgumentException("string is null or empty");
}
}
}
}

[AttributeUsage(AttributeTargets.Method, AllowMultiple

= false)]
public class ArgumentTypeRestrictionAttribute : DecoratorAttributeBase
{
private Type type;
public ArgumentTypeRestrictionAttribute(Type type)
{
this.type = type;
}
public override void Intercept(object target)
{
MethodCallMessageWrapper caller
= new MethodCallMessageWrapper((IMethodCallMessage)target);if (caller.ArgCount == 0)
{
return;
}
for (int i = 0; i < caller.ArgCount; i++)
{
object arg = caller.Args[i];if ((arg.GetType() != this.type) && (!arg.GetType().IsAssignableFrom(this.type)))
{
throw new ArgumentException(i.ToString());
}
}
}
}

客户类型

class User : MarshalByRefObject
{
private string name;
private string title;

[ArgumentTypeRestriction(

typeof(string))] // 提供拦截入口
[ArgumentNotEmpty()] // 提供拦截入口
public void SetUserInfo(object name, object title)
{
this.name = (string)name;
this.title = (string)title;
}
}

测试代码

[TestMethod]
public void TestCSharpAOP()
{
User user
= CustomProxy<User>.Create(new User());

user.SetUserInfo(

"joe","manager");try
{
user.SetUserInfo(
20, "manager");
}
catch (Exception ex)
{
Assert.AreEqual
<string>("0", ex.Message);
}
try
{
user.SetUserInfo(
"", "manager");
}
catch (Exception ex)
{
Assert.AreEqual
<string>("string is null or empty", ex.Message);
}
}

收录这段代码只是为了了解下.NET下实现AOP机制的基本方式。如果想在项目中使用AOP机制,我觉得还是使用Enterprise Lirbrary 的PIAB吧。

自己实现AOP的框架需没有太大必要了。

另外书中还列举了一种使用MSIL的实现方式。感觉比较复杂没有太深入。

本文有点炒剩饭。。。纯属个人备忘