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

推荐订阅源

H
Help Net Security
博客园 - Franky
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
博客园_首页
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recent Announcements
Recent Announcements
Scott Helme
Scott Helme
有赞技术团队
有赞技术团队
M
MIT News - Artificial intelligence
C
CERT Recently Published Vulnerability Notes
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
L
LangChain Blog
L
LINUX DO - 最新话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Hacker News: Front Page
MyScale Blog
MyScale Blog
P
Palo Alto Networks Blog
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
AI
AI
T
Troy Hunt's Blog
Microsoft Azure Blog
Microsoft Azure Blog
阮一峰的网络日志
阮一峰的网络日志
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Vercel News
Vercel News
Microsoft Security Blog
Microsoft Security Blog
罗磊的独立博客
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
人人都是产品经理
人人都是产品经理
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
S
Security @ Cisco Blogs
Cloudbric
Cloudbric
E
Exploit-DB.com RSS Feed
Attack and Defense Labs
Attack and Defense Labs

博客园 - mahope

一个算法题解 在ASP.NET web 站点中使用log4net (1.2.9) 解决Web Service中传递子类实例时,序列化的问题。 Q & A:Does ASP.NET support one-way Web Service operations? openwave:Malformed server response web 项目的 csproj 文件要有对应的.webinfo文件才能在vs里面打开 - mahope 软件需求规范(SRS)指南 写需求文档的一般原则 删除everyone对c:的 访问权限后,运行asp.net出现DirectoryNotFoundException未找到路径“C:\”的一部分 - mahope - 博客园 NHibernate Mapping文件中如何指定类的字节数组属性 NHibernate.ADOException : Unable to perform find 对于事件不能调用BeginInvoke,可改用另外一层包装 IBM面试题试解(关于50条狗、50个人、病狗) Einstein's Riddle 爱因斯坦出的智力题? Artificial intelligence: Solving problems for the real world 一些面向对象的设计法则 重构、分支语句、虚函数、抽象函数与多态--《重构:改善既有代码设计》之读书心得 NHibernate 执行内嵌类(Nested Class)查询 为内嵌类(Nested Class)配置NHibernate的O/R Mapping文件
在.NET 中实现 AOP
mahope · 2006-03-29 · via 博客园 - mahope

软件工程中的大多数思想都是集中在管理复杂度上面的--
结构化编程尝试通过粗粒度的代码与设计划分来降低复杂度;
面向对象编程尝试通过建立结合状态与行为的抽象体来降低复杂度;
基于组件的软件尝试通过基于抽象接口和协议划分应用程序模块来降低复杂度。

基于组件的软件的梦想是构造一个世界,让水平一般的程序员就能使用高级语言和工具将组件组装起来。这当然假设这个世界里面的问题域能被分解成相互之间通过简单的方法调用进行交互的各种离散组件。

基于组件的软件的前提却忽略了这样一个事实,一个程序的特定方面倾向于分散到一个应用的多个部分。安全性就是这样的一个方面,线程管理也是,并发控制也是,这个列表会很长。

不可避免地,一个应用趋于被众多处理那些不是问题域中心的程序方面的代码片断污染。通常,这些方面又倾向于跨问题域,因此需要可复用的解决方案。致力提供机制来解决这类问题的就是AOP(面向方面编程),一个在1997年先后被Gregor Kiczales,和Xeros PARC 提出来的术语。

CLR的AOP机制基本上就是将方法调用看作消息交换。

下面用代码说明这个机制:

using System;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Services;
using System.Runtime.Remoting.Contexts;
using System.Threading;
using System.Diagnostics;

namespace MsgAsMethodCalls
{
    
public interface ICaculator
    
{
        
double Add(double x, double y);
        
double Multiply(double x, double y);
    }


    
public class MyProxy : RealProxy
    
{
        
public MyProxy() : base(typeof(ICaculator)) { }

        
public override IMessage Invoke(IMessage msg)
        
{
            
if (msg as IMethodCallMessage != null)
            
{
                IMessage response 
= Program.ProcessMessage(msg as IMethodCallMessage);
                
return response;
            }

            
return null;
        }

    }


    
public class PriorityProxy : RealProxy
    
{
        
readonly MarshalByRefObject target;
        
readonly ThreadPriority level;

        
public PriorityProxy(MarshalByRefObject target,
            Type type,
            ThreadPriority level)
            : 
base(type)
        
{
            
this.target = target;
            
this.level = level;
        }


        
public override IMessage Invoke(IMessage request)
        
{
            IMethodCallMessage call 
= (IMethodCallMessage)request;

            Program.WireTap(call);

// step 1: adjust priority
            Thread here = Thread.CurrentThread;
            ThreadPriority old 
= here.Priority;
            here.Priority 
= level;
// step 2: forward call
            IMessage response = null;

            IConstructionCallMessage ctor 
= call as IConstructionCallMessage;

            
if (ctor != null)
            
{
                
// we are holding a TP, so grab its RP
                RealProxy defaultProxy = RemotingServices.GetRealProxy(target);
                
// as intermediatoe RP to invoke constructor
                defaultProxy.InitializeServerObject(ctor);
                
// get OUR TP
                MarshalByRefObject tp = (MarshalByRefObject)this.GetTransparentProxy();
                
// return a message containing our TP as the result of the constuctor call
                response = EnterpriseServicesHelper.CreateConstructionReturnMessage(ctor, tp);
            }

            
else
            
{
                response 
= RemotingServices.ExecuteMessage(target, call);
            }


// step 3: restore old priority
            here.Priority = old;
// step 4: return response message to TP
            return response;
        }

    }


    [AttributeUsage(AttributeTargets.Class)]
    
public class PriorityProxyAttribute : ProxyAttribute
    
{
        ThreadPriority level;
        
public PriorityProxyAttribute(ThreadPriority level)
        
{
            
this.level = level;
        }


        
public override MarshalByRefObject CreateInstance(Type t)
        
{
// note that we delegate to our base to get an
// uninitialized instance!
            MarshalByRefObject target = base.CreateInstance(t);
            PriorityProxy rp 
= new PriorityProxy(target, t, level);
            
return (MarshalByRefObject)rp.GetTransparentProxy();
        }

    }


    
public class PriorityProperty : IContextProperty
    
{
        ThreadPriority level;
        
public ThreadPriority Level get return level; } }
        
internal PriorityProperty(ThreadPriority level)
        
this.level = level; }

// IContextProperty members
        public string Name get return "ThreadPriority"; } }
        
public bool IsNewContextOK(Context ctx)
        
{
            
return true;
        }


        
public void Freeze(Context ctx) { }
    }


    
public class PriorityAttribute : Attribute, IContextAttribute
    
{
        ThreadPriority level;
        
internal PriorityAttribute(ThreadPriority level)
        
this.level = level; }

// IContextAttribute members
        public bool IsContextOK(Context current,
            IConstructionCallMessage ctor)
        
{
// Our property must be present!
            object prop = current.GetProperty("ThreadPriority");
            
if (prop == nullreturn false;
// and its level must match the attribute's
            PriorityProperty pp = (PriorityProperty)prop;
            
return pp.Level == this.level;
        }


        
public void GetPropertiesForNewContext(
            IConstructionCallMessage ctor)
        
{
// create new properties
            IContextProperty prop = new PriorityProperty(this.level);
// associate property with constructor call
            ctor.ContextProperties.Add(prop);

            ctor.ContextProperties.Add(
new TimingProperty());

            ctor.ContextProperties.Add(
new BoostProperty());

            ctor.LogicalCallContext.SetData(
"clientpriority"new EnvoyData(Thread.CurrentThread.Priority));
        }

    }


    
public abstract class DefaultSink : IMessageSink
    
{
        
readonly protected IMessageSink next;
        
public DefaultSink(IMessageSink next)
        
{
            
this.next = next;
        }


        
public IMessageSink NextSink get return next; } }

        
public virtual IMessage SyncProcessMessage(IMessage request)
        
{
            IMessage response 
= next.SyncProcessMessage(request);
            
return response;
        }


        
public virtual IMessageCtrl AsyncProcessMessage(IMessage request,
            IMessageSink upcall)
        
{
            IMessageCtrl ctrl 
= next.AsyncProcessMessage(request, upcall);
            
return ctrl;
        }

    }


    
public class ServerTimingSink : DefaultSink
    
{
        
public ServerTimingSink(IMessageSink next)
            : 
base(next)
        
{ }

        [ContextStatic]
        
static internal long totalTicks = 0;

        
public override IMessage SyncProcessMessage(IMessage r)
        
{
            
long start = DateTime.Now.Ticks;
            IMessage p 
= next.SyncProcessMessage(r);
            
long end = DateTime.Now.Ticks;
            totalTicks 
+= end - start;
            
return p;
        }

    }


    
public class ClientTimingSink : DefaultSink
    
{
        
public ClientTimingSink(IMessageSink next)
            : 
base(next)
        
{ }

        
public override IMessage SyncProcessMessage(IMessage r)
        
{
            
long start = DateTime.Now.Ticks;
            IMessage p 
= next.SyncProcessMessage(r);
            
long end = DateTime.Now.Ticks;
            ServerTimingSink.totalTicks 
+= end - start;
            
return p;
        }

    }


    
public class TimingProperty
        : IContextProperty,
        IContributeClientContextSink,
        IContributeServerContextSink
    
{
        
IContributeClientContextSink Members

        
IContributeServerContextSink Members

        
IContextProperty Members
    }


    
internal class EnvoyData : ILogicalThreadAffinative
    
{
        
internal ThreadPriority clientPriority;
        
internal EnvoyData(ThreadPriority level)
        
{
            
this.clientPriority = level;
        }

    }


    
public class PriorityEnvoySink : DefaultSink
    
{
        
public PriorityEnvoySink(IMessageSink next) : base(next) { }

        
public override IMessage SyncProcessMessage(IMessage request)
        
{
            IMethodCallMessage call 
= (IMethodCallMessage)request;
            ThreadPriority p 
= Thread.CurrentThread.Priority;
            EnvoyData ed 
= new EnvoyData(p);
            call.LogicalCallContext.SetData(
"clientpriority", ed);
            
return next.SyncProcessMessage(call);
        }

    }


    
public class PriorityServerSink : DefaultSink
    
{
        
public PriorityServerSink(IMessageSink next) : base(next) { }

        
public override IMessage SyncProcessMessage(IMessage request)
        
{
// grab caller's priority from call context
            IMethodCallMessage call = (IMethodCallMessage)request;
            LogicalCallContext cc 
= call.LogicalCallContext;
            EnvoyData ed 
= (EnvoyData)cc.GetData("clientpriority");
            cc.FreeNamedDataSlot(
"clientpriority");
// proceed to boost-dispatch-unboost
            Thread here = Thread.CurrentThread;
            ThreadPriority old 
= here.Priority;
            
if (ed.clientPriority != ThreadPriority.Highest)
                here.Priority 
= ed.clientPriority + 1;
            IMessage resp 
= next.SyncProcessMessage(call);
            
if (ed.clientPriority != ThreadPriority.Highest)
                here.Priority 
= old;
            
return resp;
        }

    }


    
public class BoostProperty :
        IContextProperty,
        IContributeServerContextSink,
        IContributeEnvoySink
    
{
        
IContextProperty Members

        
IContributeServerContextSink Members

        
IContributeEnvoySink Members
}


    
public class MyCalc : ContextBoundObject, ICaculator
    
{
        
public static MyCalc Create(ThreadPriority level)
        
{
            MyCalc target 
= new MyCalc();
            PriorityProxy rp 
= new PriorityProxy(target, typeof(MyCalc), level);
            
return (MyCalc)rp.GetTransparentProxy();
        }


        
private MyCalc() { }

        
public double Add(double x, double y) return x + y; }
        
public double Multiply(double x, double y) return x * y; }
    }



    [PriorityProxy(ThreadPriority.Highest)]
    
public class MyCalc3 : ContextBoundObject, ICaculator
    
{
        
public double Add(double x, double y) {
            Console.WriteLine(Thread.CurrentThread.Priority);
            
return x + y; 
        }

        
public double Multiply(double x, double y) return x * y; }
    }


    [Priority(ThreadPriority.Highest)]
    
public class MyCalc5 : ContextBoundObject, ICaculator
    
{
        
public double Add(double x, double y) 
// grab the object's context
            Context here = Thread.CurrentContext;
// fecth the priority property
            IContextProperty p = here.GetProperty("ThreadPriority");
            PriorityProperty pp 
= (PriorityProperty)p;
            Debug.Assert(pp.Level 
== ThreadPriority.Highest);

            Console.WriteLine(Thread.CurrentThread.Priority);

            
return x + y; 
        }

        
public double Multiply(double x, double y) return x * y; }
    }


    
class Program
    
{
        
public static void WireTap(IMethodMessage msg){
            IMethodCallMessage call 
= (IMethodCallMessage)msg;
            Console.WriteLine(
"<{0}>",call.MethodName);
            
for(int i=0;i<call.ArgCount;++i)
                Console.WriteLine(
"<{0}>{1}</{0}>",
                    call.GetArgName(i),
                    call.GetArg(i));

            Console.WriteLine(
"</{0}>",call.MethodName);
        }


        
public static IMethodReturnMessage ProcessMessage(IMethodCallMessage request)
        
{
            
switch (request.MethodName)
            
{
                
case "Add":
                    
{
                        
double x = (double)request.GetInArg(0);
                        
double y = (double)request.GetInArg(1);
                        
double result = x + y;
                        
return new ReturnMessage(result, null0null, request);
                    }

                
case "Multiply":
                    
{
                        
double x = (double)request.GetInArg(0);
                        
double y = (double)request.GetInArg(1);
                        
double result = x * y;
                        
return new ReturnMessage(result, null0null, request);
                    }

                
default:
                    
{
                        
string exm = string.Format("{0} not implemented",
                            request.MethodName);
                        Exception ex 
= new NotImplementedException(exm);
                        
return new ReturnMessage(ex, request);
                    }

            }

        }


        
static void Main(string[] args)
        
{
// isinst
            MyProxy rp = new MyProxy();
            
object tp = rp.GetTransparentProxy();
            ICaculator calc 
= tp as ICaculator;

            Debug.Assert(calc 
!= null);

            
double result = calc.Add(34);

            Debug.Assert(result 
== 7);

// factory method
            calc = MyCalc.Create(ThreadPriority.Highest);
            result 
= calc.Add(34);

            Debug.Assert(result 
== 7);

 
// ProxyAttribute
            calc = new MyCalc3();
            result 
= calc.Add(34);

            Debug.Assert( result 
== 7);

// ContextProperty
            calc = new MyCalc5();
            result 
= calc.Add(34);

            Debug.Assert(result 
== 7);
        }

    }

}