/// <summary> /// 重写方法。 /// </summary> /// <param name="instanceAst">方法“this”上下文。</param> /// <param name="classEmitter">类。</param> /// <param name="methodInfo">被重写的方法。</param> /// <param name="attributeDatas">属性。</param> public static MethodEmitter DefineMethodOverride(AstExpression instanceAst, ClassEmitter classEmitter, MethodInfo methodInfo, IList <CustomAttributeData> attributeDatas) { var methodAttributes = methodInfo.Attributes; if ((methodAttributes & MethodAttributes.Abstract) == MethodAttributes.Abstract) { methodAttributes ^= MethodAttributes.Abstract; } bool flag = true; var overrideEmitter = classEmitter.DefineMethodOverride(ref methodInfo, methodAttributes); var paramterEmitters = overrideEmitter.GetParameters(); #if NET40 foreach (var attributeData in attributeDatas.Where(x => InterceptAttributeType.IsAssignableFrom(x.Constructor.DeclaringType))) #else foreach (var attributeData in attributeDatas.Where(x => InterceptAttributeType.IsAssignableFrom(x.AttributeType))) #endif { if (flag) { flag = false; } overrideEmitter.SetCustomAttribute(attributeData); } if (flag && !methodInfo.DeclaringType.IsInterface && !methodInfo.IsDefined(InterceptAttributeType, true)) { overrideEmitter.Append(Call(instanceAst, methodInfo, paramterEmitters)); return(overrideEmitter); } AstExpression[] arguments = null; var variable = Variable(typeof(object[])); overrideEmitter.Append(Assign(variable, Array(paramterEmitters))); if (overrideEmitter.IsGenericMethod) { arguments = new AstExpression[] { Constant(overrideEmitter), instanceAst, Constant(methodInfo), variable }; } else { var tokenEmitter = classEmitter.DefineField($"____token__{methodInfo.Name}", typeof(MethodInfo), FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.InitOnly); classEmitter.TypeInitializer.Append(Assign(tokenEmitter, Constant(methodInfo))); var proxyEmitter = classEmitter.DefineField($"____proxy__{methodInfo.Name}", typeof(MethodInfo), FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.InitOnly); classEmitter.TypeInitializer.Append(Assign(proxyEmitter, Constant(overrideEmitter))); arguments = new AstExpression[] { proxyEmitter, instanceAst, tokenEmitter, variable }; } BlockAst blockAst; if (paramterEmitters.Any(x => x.RuntimeType.IsByRef)) { var finallyAst = Block(typeof(void)); for (int i = 0; i < paramterEmitters.Length; i++) { var paramterEmitter = paramterEmitters[i]; if (!paramterEmitter.IsByRef) { continue; } finallyAst.Append(Assign(paramterEmitter, Convert(ArrayIndex(variable, i), paramterEmitter.ParameterType))); } blockAst = Try(methodInfo.ReturnType, finallyAst); } else { blockAst = Block(methodInfo.ReturnType); } if (overrideEmitter.ReturnType.IsClass && typeof(Task).IsAssignableFrom(overrideEmitter.ReturnType)) { if (overrideEmitter.ReturnType.IsGenericType) { blockAst.Append(Call(InterceptAsyncGenericMethodCall.MakeGenericMethod(overrideEmitter.ReturnType.GetGenericArguments()), New(InterceptContextCtor, arguments))); } else { blockAst.Append(Call(InterceptAsyncMethodCall, New(InterceptContextCtor, arguments))); } } else if (overrideEmitter.ReturnType == typeof(void)) { blockAst.Append(Call(InterceptMethodCall, New(InterceptContextCtor, arguments))); } else { blockAst.Append(Call(InterceptGenericMethodCall.MakeGenericMethod(overrideEmitter.ReturnType), New(InterceptContextCtor, arguments))); } overrideEmitter.Append(blockAst); return(overrideEmitter); }