相比之前一篇remoting实现的AOP,这次用RealProxy和ProxyAttribute实现的简单许多。
代码如下:
首先是透明代理,该类在运行时会自动根据类的特性去代理其被代理对象
using System;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Services;
using System.Collections.Generic;
namespace AOPProxy.AOP
{
public class AOPProxyBase : RealProxy
{
private Dictionary<string, MarshalByRefObject> _targetDict = null;
private Dictionary<string, IAOPInterceptAchieveBase> _aopAchieveDict = new Dictionary<string, IAOPInterceptAchieveBase>();
private static Dictionary<string, AOPProxyBase> _aopProxy = new Dictionary<string, AOPProxyBase>();
private AOPProxyBase(Type type, Dictionary<string, MarshalByRefObject> targetDict, Dictionary<string, IAOPInterceptAchieveBase> aopAchieveDict)
: base(type)
{
this._targetDict = targetDict;
this._aopAchieveDict = aopAchieveDict;
}
public static AOPProxyBase GetBaseProxyInstance(Type type, Dictionary<string, MarshalByRefObject> targetDict, Dictionary<string, IAOPInterceptAchieveBase> aopAchieveDict)
{
string typeName = type.FullName;
if (_aopProxy.ContainsKey(typeName)==false)
{
_aopProxy.Add(typeName, new AOPProxyBase(type, targetDict, aopAchieveDict));
}
return _aopProxy[typeName];
}
//对应添加了AOPProxy特性的类,系统会自动调用该方法
public override IMessage Invoke(IMessage msg)
{
string targetTypeName = Convert.ToString(msg.Properties["__TypeName"]).Split(',')[0];
IMethodReturnMessage result = null;
bool isAOP = false;//是否需要AOP拦截
//构造函数,只有ContextBoundObject(Inherit from MarshalByRefObject)对象才能截获构造函数
if (msg is IConstructionCallMessage)
{
IConstructionCallMessage cusMethod = msg as IConstructionCallMessage;
RealProxy defaultProxy = RemotingServices.GetRealProxy(_targetDict[targetTypeName]);
//如果不做下面这一步,_targetDict[targetTypeName]还是一个没有直正实例化被代理对象的透明代理,
//这样的话,会导致没有直正构建对象。
defaultProxy.InitializeServerObject(cusMethod);
//本类是一个RealProxy,它可通过GetTransparentProxy函数得到透明代理
result = EnterpriseServicesHelper.CreateConstructionReturnMessage(cusMethod, (MarshalByRefObject)GetTransparentProxy());
}
else if (msg is IMethodCallMessage)
{
IMethodCallMessage method = (IMethodCallMessage)msg;
AOPMethodBaseAttribute aopMethod = null;
//查询目标方法是否使用了启用AOP的AOPMethodAttribute
foreach (Attribute attr in method.MethodBase.GetCustomAttributes(false))
{
if (attr is AOPMethodBaseAttribute)
{
aopMethod = attr as AOPMethodBaseAttribute;
isAOP = true;
break;
}
}
if (isAOP)//需要AOP拦截
{
if (aopMethod.AopLocation == AOPLocation.Before)
{
bool check = _aopAchieveDict[aopMethod.NameSpaceClass].BeforeAchieve(method);
if (check)
{
result = RemotingServices.ExecuteMessage(_targetDict[targetTypeName], method);
}
}
else if(aopMethod.AopLocation == AOPLocation.After)
{
result = RemotingServices.ExecuteMessage(_targetDict[targetTypeName], method);
_aopAchieveDict[aopMethod.NameSpaceClass].AfterAchieve(result);
}
else
{
bool check = _aopAchieveDict[aopMethod.NameSpaceClass].BeforeAchieve(method);
if (check)
{
result = RemotingServices.ExecuteMessage(_targetDict[targetTypeName], method);
_aopAchieveDict[aopMethod.NameSpaceClass].AfterAchieve(result);
}
}
}
else//不需要AOP拦截,直接执行目标方法
{
result = RemotingServices.ExecuteMessage(_targetDict[targetTypeName], method);
}
}
return result;
}
}
}
using System;
using System.Runtime.Remoting.Proxies;
using System.Collections.Generic;
namespace AOPProxy.AOP
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class AOPProxyBaseAttribute : ProxyAttribute
{
private static Dictionary<string, IAOPInterceptAchieveBase> _aopAchieveDict = new Dictionary<string, IAOPInterceptAchieveBase>();
private static Dictionary<string, MarshalByRefObject> _targetDict = new Dictionary<string, MarshalByRefObject>();
public AOPProxyBaseAttribute(Type type)
{
try
{
object obj = Activator.CreateInstance(type);
if (obj is IAOPInterceptAchieveBase)
{
if(_aopAchieveDict.ContainsKey(((IAOPInterceptAchieveBase)obj).GetType().FullName)==false)
_aopAchieveDict.Add(((IAOPInterceptAchieveBase)obj).GetType().FullName, (IAOPInterceptAchieveBase)obj);
}
else
{
throw new ArgumentException("特性的参数必须是实现IAOPInterceptAchieve接口的对象");
}
}
catch (MissingMemberException e)
{
throw new MissingMemberException("实现IAOPInterceptAchieve接口的自定义代理类必须定义无参的构造函数",e);
}
}
//覆写CreateInstance函数,返回我们自建的代理
//该方法会在需要被代理的类在实例化时被创建
public override MarshalByRefObject CreateInstance(Type serverType)//serverType是被AOPAttribute修饰的类
{
//未初始化的实例的默认透明代理
MarshalByRefObject target = base.CreateInstance(serverType); //得到未初始化的实例
if (_targetDict.ContainsKey(serverType.FullName) == false)
_targetDict.Add(serverType.FullName, target);
//得到自定义的真实代理
AOPProxyBase rp = AOPProxyBase.GetBaseProxyInstance(serverType, _targetDict, _aopAchieveDict);//new AOPProxyBase(serverType, _targetDict, _aopAchieveDict);
return (MarshalByRefObject)rp.GetTransparentProxy();
}
}
}
下面是方法的特性,表示了被代理类的那些方法需要被拦截,以及需要拦截的位置
using System;
namespace AOPProxy.AOP
{
[AttributeUsage(AttributeTargets.Method,AllowMultiple=false)]
public class AOPMethodBaseAttribute : Attribute
{
private AOPLocation _aopLocation;
private string _nameSpaceClass;
public string NameSpaceClass
{
get { return _nameSpaceClass; }
set { _nameSpaceClass = value; }
}
public AOPLocation AopLocation
{
get { return _aopLocation; }
set { _aopLocation = value; }
}
public AOPMethodBaseAttribute(AOPLocation loc,string ncl)
{
this._aopLocation = loc;
this._nameSpaceClass = ncl;
}
}
public enum AOPLocation
{
Before,
After,
All
}
}
最后就是一个拦截方法接口
using System.Runtime.Remoting.Messaging;
namespace AOPProxy.AOP
{
/// <summary>
/// 被拦截方法的前后的额外处理逻辑接口
/// </summary>
public interface IAOPInterceptAchieveBase
{
bool BeforeAchieve(IMethodCallMessage callMsg);
bool AfterAchieve(IMethodReturnMessage returnMsg);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AOPProxy.AOP;
namespace AOPProxy
{
class Program
{
static void Main(string[] args)
{
Test1Instance t1 = new Test1Instance();
t1.Rxb1Method();
Console.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
Test2Instance t = new Test2Instance();
t.Rxb2Method();
t.Test2Method("我是目标方法的参数");
Console.ReadLine();
}
}
[AOPProxyBaseAttribute(typeof(AOPDataProxy))]
[AOPProxyBaseAttribute(typeof(AOPLogProxy))]
public class Test2Instance : TestBase
{
[AOPMethodBaseAttribute(AOPLocation.All, "AOPProxy.AOPDataProxy")]
public string Test2Method(string s)
{
Console.WriteLine("TestMethod2-Action…要被拦截的方法…");
return "rxb";
}
[AOPMethodBaseAttribute(AOPLocation.All, "AOPProxy.AOPLogProxy")]
public void Rxb2Method()
{
Console.WriteLine("RxbMethod2-Action…要被拦截的方法…");
}
}
[AOPProxyBaseAttribute(typeof(AOPLogProxy))]
public class Test1Instance : TestBase
{
public string Test1Method(string s)
{
Console.WriteLine("TestMethod1-Action…要被拦截的方法…");
return "rxb";
}
[AOPMethodBaseAttribute(AOPLocation.Before, "AOPProxy.AOPLogProxy")]
public void Rxb1Method()
{
Console.WriteLine("RxbMethod1-Action…要被拦截的方法…");
}
}
public class TestBase : ContextBoundObject{}
}
运行结果如下: