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

推荐订阅源

Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
A
About on SuperTechFans
IT之家
IT之家
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Blog — PlanetScale
Blog — PlanetScale
aimingoo的专栏
aimingoo的专栏
云风的 BLOG
云风的 BLOG
The GitHub Blog
The GitHub Blog
Vercel News
Vercel News
G
Google Developers Blog
J
Java Code Geeks
宝玉的分享
宝玉的分享
T
Tailwind CSS Blog
Cloudbric
Cloudbric
L
LINUX DO - 最新话题
MyScale Blog
MyScale Blog
H
Heimdal Security Blog
PCI Perspectives
PCI Perspectives
Attack and Defense Labs
Attack and Defense Labs
S
Security @ Cisco Blogs
Latest news
Latest news
I
Intezer
L
Lohrmann on Cybersecurity
C
CXSECURITY Database RSS Feed - CXSecurity.com
月光博客
月光博客
T
Threatpost
博客园 - 【当耐特】
S
Schneier on Security
P
Privacy International News Feed
G
GRAHAM CLULEY
T
Tenable Blog
AWS News Blog
AWS News Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
博客园 - Franky
Engineering at Meta
Engineering at Meta
美团技术团队
S
Secure Thoughts
T
Troy Hunt's Blog
Microsoft Security Blog
Microsoft Security Blog
SecWiki News
SecWiki News
V
Visual Studio Blog
人人都是产品经理
人人都是产品经理
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cisco Talos Blog
Cisco Talos Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Martin Fowler
Martin Fowler
Webroot Blog
Webroot Blog
Google DeepMind News
Google DeepMind News
H
Hackread – Cybersecurity News, Data Breaches, AI and More

博客园 - 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的实现方式。感觉比较复杂没有太深入。

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