转,C#动态代理实现AOP

自: 

https://blog.csdn.net/weixin_37390956/article/details/79947976

搬砖,

--------------------
/// <summary>
/// 创建动态代理方法
/// </summary>
/// <param name="typeBuilder">类型构造器</param>
/// <param name="method">方法元数据</param>
/// <param name="realObjectField">实际对象</param>
/// <param name="aspectFields">切面</param>
private static void EmitMethod(TypeBuilder typeBuilder, MethodInfo method, FieldBuilder realObjectField, List<AspectField> aspectFields)
{
//参数列表
var parameters = method.GetParameters();
//动态实例
var emitter = Sigil.NonGeneric.Emit.BuildInstanceMethod(method.ReturnType, parameters.Select(i => i.ParameterType).ToArray(), typeBuilder, method.Name, MethodAttributes.Public | MethodAttributes.Virtual);

//label base
var lbCallBase = emitter.DefineLabel();
//label return
var lbReturn = emitter.DefineLabel();

//方法上下文
var methodContextLocal = emitter.DeclareLocal(typeof(MethodContext));
//返回
var returnLocal = method.ReturnType != typeof(void) ? emitter.DeclareLocal(method.ReturnType) : null;
//本地存储
var objArrayLocal = emitter.DeclareLocal(typeof(object[]));
//异常
var exceptionLocal = emitter.DeclareLocal<Exception>();
//切面列表
var aspects = method.GetCustomAttributes(typeof(AspectAttribute), false).Cast<AspectAttribute>().Concat(AspectFactory.GlobalAspects).ToList();
//是否包含异常切面
bool hasException = aspects.Any(i => i.GetType().GetMethod("ExceptionFilter").DeclaringType != typeof(AspectAttribute));
//异常捕捉块
Sigil.ExceptionBlock tryBlock = null;
//方法名
string methodName = method.Name;
if (aspects.Any())
{
//给参数分配内存
emitter
.LoadConstant(parameters.Length)
.NewArray<object>()
.StoreLocal(objArrayLocal); // var parameters = new object[parameters.Length];

//给参数填充实际值
for (int i = 0; i < parameters.Length; i++)
{
emitter
.LoadLocal(objArrayLocal)
.LoadConstant(i)
.LoadArgument((ushort)(i + 1))
.Box(parameters[i].ParameterType, true)
.StoreElement<object>(); // parameters[i] = paramN;
}

//通过使用该方法的内部元数据表示形式 (句柄) 获取方法的信息
emitter
.LoadConstant(method)
.Call(typeof(MethodBase).GetMethod("GetMethodFromHandle", new[] { typeof(RuntimeMethodHandle) }))
.CastClass<MethodInfo>() // methodof(Method)

//加载真实方法对象
.LoadArgument(0)
.LoadField(realObjectField) // this.realObject

//加载自定义的上下文
.LoadLocal(objArrayLocal)
.Call(typeof(ProxyBase).GetMethod("GetMethodContext", BindingFlags.Static | BindingFlags.NonPublic))
.StoreLocal(methodContextLocal); // methodContextLocal = GetMethodContext(methodof(Method), this.realObject, parameters
}

var currentMethodAspects = new List<AspectField>();
//根据切面的优先级排序
foreach (var aspect in aspects.OrderBy(i => i.EnterPriority))
{
//创建切面
var field = typeBuilder.DefineField("aspectField_" + Guid.NewGuid(), typeof(AspectAttribute), FieldAttributes.Static | FieldAttributes.Private);
aspectFields.Add(new AspectField { Aspect = aspect, Field = field });
currentMethodAspects.Add(new AspectField { Aspect = aspect, Field = field });

//调用切面前处理
emitter
.LoadField(field)
.LoadLocal(methodContextLocal)
.CallVirtual(typeof(AspectAttribute).GetMethod(GetName(aspect.MethodEnter), BindingFlags.Instance | BindingFlags.Public));

//如果方法有返回则试图获取 返回值 返回如果不为空则标志lbreturn 直接返回结束
if (method.ReturnType != typeof(void))
{
emitter
.LoadLocal(methodContextLocal)
.Call(typeof(MethodContext).GetProperty("ReturnValue").GetGetMethod())
.BranchIfTrue(lbReturn);
}
}

//Chama o método base 标记调用父方法
emitter.MarkLabel(lbCallBase);

//如果包含异常捕捉切面则添加一个trycatch块
if (hasException)
tryBlock = emitter.BeginExceptionBlock();

if (aspects.Any() && method.ReturnType != typeof(void)) //Armazena o objeto retornado no ReturnValue caso haja aspectos
emitter.LoadLocal(methodContextLocal);

emitter
.LoadArgument(0)
.LoadField(realObjectField);
for (int i = 0; i < parameters.Length; i++)
emitter.LoadArgument((ushort)(i + 1));
//调用实际的方法
emitter.CallVirtual(method); //realObject.Method(parameters...);
//保存返回值
if (method.ReturnType != typeof(void))
emitter.StoreLocal(returnLocal);


//Armazena o objeto retornado no ReturnValue caso haja aspectos
//设置methodcontext里的返回值
if (method.ReturnType != typeof(void) && aspects.Any())
{
emitter
.LoadLocal(returnLocal)
.Box(method.ReturnType, true)
.Call(typeof(MethodContext).GetProperty("ReturnValue").GetSetMethod());
}

//开始调用切面里面的异常处理
if (hasException)
{
var catchBlock = emitter.BeginCatchBlock<Exception>(tryBlock);
emitter.StoreLocal(exceptionLocal);

foreach (var aspect in currentMethodAspects.Where(i => i.Aspect.GetType().GetMethod("ExceptionFilter").DeclaringType != typeof(AspectAttribute)))
emitter
.LoadField(aspect.Field)
.LoadLocal(methodContextLocal)
.LoadLocal(exceptionLocal)
.CallVirtual(typeof(AspectAttribute).GetMethod("ExceptionFilter", BindingFlags.Instance | BindingFlags.Public));
//切面异常处理结束之后重新抛出异常 不影响后续流程
emitter
.ReThrow()
.EndCatchBlock(catchBlock)
.EndExceptionBlock(tryBlock);
}

//循环按照优先级调用切面后处理
emitter.MarkLabel(lbReturn);
foreach (var aspect in currentMethodAspects.OrderBy(i => i.Aspect.ExitPriority))
{
emitter
.LoadField(aspect.Field)
.LoadLocal(methodContextLocal)
.CallVirtual(typeof(AspectAttribute).GetMethod(GetName(aspect.Aspect.MethodExit), BindingFlags.Instance | BindingFlags.Public));
}
//存储返回值
if (method.ReturnType != typeof(void))
{
if (aspects.Any())
{
emitter
.LoadLocal(methodContextLocal)
.Call(typeof(MethodContext).GetProperty("ReturnValue").GetGetMethod())
.UnboxAny(method.ReturnType, true)
.StoreLocal(returnLocal);

}

if (method.ReturnType != typeof(void))
emitter.LoadLocal(returnLocal);
}
//返回
emitter.Return();
//生成代理方法
var newMethod = emitter.CreateMethod();
typeBuilder.DefineMethodOverride(newMethod, method);
}
---------------------
作者:我们生活在果壳中
来源:CSDN
原文:https://blog.csdn.net/weixin_37390956/article/details/79947976

----------------------

其他参考,,,AOP从静态代理到动态代理(Emit实现)详解   (这篇不错):  https://www.jb51.net/article/147526.htm

posted @ 2018-12-20 14:51  以函  阅读(1507)  评论(0编辑  收藏  举报