关于静态代理请参考:
http://www.hechunbo.com/index.php/archives/209.html
动态代理 的特点是程序自动生成代理类,不用再根据业务来一个一个类写了。
是运行时代理。
/// <summary> /// 标记方法特性,在调用类中的方法时,调用before /// </summary> public class ActionAttribute : ActionBaseAttribute { public override void Before(string @method, object[] parameters) { Console.WriteLine("ActionAttribute before,method:" + method); } public override object After(string @method, object result) { Console.WriteLine(" ActionAttribute after,method:" + method); return base.After(method, result); } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)] public class ActionBaseAttribute : Attribute { public virtual void Before(string @method, object[] parameters) { } public virtual object After(string @method, object result) { return result; } }
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] public class InterceptorBaseAttribute : Attribute { public virtual object Invoke(object @object, string @method, object[] parameters) { return @object.GetType().GetMethod(@method).Invoke(@object, parameters); } } /// <summary> /// 定义类的特性。也是在方法前后调用 ,但是先办理出action日志 。因为action特性标记在方法上。 /// </summary> public class InterceptorAttribute : InterceptorBaseAttribute { public override object Invoke(object @object, string @method, object[] parameters) { Console.WriteLine("InterceptorAttribute before invokc"); object obj = null; try { obj = base.Invoke(@object, method, parameters); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine("InterceptorAttribute after invoke"); return obj; } } public interface IBusinessClass { void add(); }
public interface IBusinessClass { void add(); } [Interceptor] public class Business : IBusinessClass { [Action] public void add() { Console.WriteLine("add method"); } }
public class DynamicProxy { public static TInterface CreateProxyOfRealize<TInterface, TImp>() where TImp : class, new() where TInterface : class { return Invoke<TInterface, TImp>(); } public static TProxyClass CreateProxyOfInherit<TProxyClass>() where TProxyClass : class, new() { return Invoke<TProxyClass, TProxyClass>(true); } private static TInterface Invoke<TInterface, TImp>(bool inheritMode = false) where TImp : class, new() where TInterface : class { var impType = typeof (TImp); string nameOfAssembly = impType.Name + "ProxyAssembly"; string nameOfModule = impType.Name + "ProxyModule"; string nameOfType = impType.Name + "Proxy"; var assemblyName = new AssemblyName(nameOfAssembly); var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); var moduleBuilder = assembly.DefineDynamicModule(nameOfModule); //var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); //var moduleBuilder = assembly.DefineDynamicModule(nameOfModule, nameOfAssembly + ".dll"); TypeBuilder typeBuilder; if (inheritMode) typeBuilder = moduleBuilder.DefineType(nameOfType, TypeAttributes.Public, impType); else typeBuilder = moduleBuilder.DefineType(nameOfType, TypeAttributes.Public, null, new[] {typeof (TInterface)}); InjectInterceptor<TImp>(typeBuilder, impType.GetCustomAttribute(typeof (InterceptorBaseAttribute)).GetType(),inheritMode); var t = typeBuilder.CreateType(); //assembly.Save(nameOfAssembly + ".dll"); return Activator.CreateInstance(t) as TInterface; } private static void InjectInterceptor<TImp>(TypeBuilder typeBuilder, Type interceptorAttributeType,bool inheritMode = false) { var impType = typeof (TImp); // ---- define fields ---- FieldBuilder fieldInterceptor = null; if (interceptorAttributeType != null) { fieldInterceptor = typeBuilder.DefineField("_interceptor", interceptorAttributeType, FieldAttributes.Private); } // ---- define costructors ---- if (interceptorAttributeType != null) { var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null); var ilOfCtor = constructorBuilder.GetILGenerator(); ilOfCtor.Emit(OpCodes.Ldarg_0); ilOfCtor.Emit(OpCodes.Newobj, interceptorAttributeType.GetConstructor(new Type[0])); ilOfCtor.Emit(OpCodes.Stfld, fieldInterceptor); ilOfCtor.Emit(OpCodes.Ret); } // ---- define methods ---- var methodsOfType = impType.GetMethods(BindingFlags.Public | BindingFlags.Instance); string[] ignoreMethodName = new[] {"GetType", "ToString", "GetHashCode", "Equals"}; foreach (var method in methodsOfType) { //ignore method if (ignoreMethodName.Contains(method.Name)) return; var methodParameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray(); MethodAttributes methodAttributes; if (inheritMode) methodAttributes = MethodAttributes.Public | MethodAttributes.Virtual; else methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final; var methodBuilder = typeBuilder.DefineMethod(method.Name, methodAttributes, CallingConventions.Standard, method.ReturnType, methodParameterTypes); var ilMethod = methodBuilder.GetILGenerator(); // set local field var impObj = ilMethod.DeclareLocal(impType); //instance of imp object var methodName = ilMethod.DeclareLocal(typeof (string)); //instance of method name var parameters = ilMethod.DeclareLocal(typeof (object[])); //instance of parameters var result = ilMethod.DeclareLocal(typeof (object)); //instance of result LocalBuilder actionAttributeObj = null; //attribute init Type actionAttributeType = null; if (method.GetCustomAttribute(typeof (ActionBaseAttribute)) != null || impType.GetCustomAttribute(typeof (ActionBaseAttribute)) != null) { //method can override class attrubute if (method.GetCustomAttribute(typeof (ActionBaseAttribute)) != null) { actionAttributeType = method.GetCustomAttribute(typeof (ActionBaseAttribute)).GetType(); } else if (impType.GetCustomAttribute(typeof (ActionBaseAttribute)) != null) { actionAttributeType = impType.GetCustomAttribute(typeof (ActionBaseAttribute)).GetType(); } actionAttributeObj = ilMethod.DeclareLocal(actionAttributeType); ilMethod.Emit(OpCodes.Newobj, actionAttributeType.GetConstructor(new Type[0])); ilMethod.Emit(OpCodes.Stloc, actionAttributeObj); } //instance imp ilMethod.Emit(OpCodes.Newobj, impType.GetConstructor(new Type[0])); ilMethod.Emit(OpCodes.Stloc, impObj); //if no attribute if (fieldInterceptor != null || actionAttributeObj != null) { ilMethod.Emit(OpCodes.Ldstr, method.Name); ilMethod.Emit(OpCodes.Stloc, methodName); ilMethod.Emit(OpCodes.Ldc_I4, methodParameterTypes.Length); ilMethod.Emit(OpCodes.Newarr, typeof (object)); ilMethod.Emit(OpCodes.Stloc, parameters); // build the method parameters for (var j = 0; j < methodParameterTypes.Length; j++) { ilMethod.Emit(OpCodes.Ldloc, parameters); ilMethod.Emit(OpCodes.Ldc_I4, j); ilMethod.Emit(OpCodes.Ldarg, j + 1); //box ilMethod.Emit(OpCodes.Box, methodParameterTypes[j]); ilMethod.Emit(OpCodes.Stelem_Ref); } } //如果存在action特性,加载实例化对象,参数,执行before方法 //dynamic proxy action before if (actionAttributeType != null) { //load arguments ilMethod.Emit(OpCodes.Ldloc, actionAttributeObj); ilMethod.Emit(OpCodes.Ldloc, methodName); ilMethod.Emit(OpCodes.Ldloc, parameters); ilMethod.Emit(OpCodes.Call, actionAttributeType.GetMethod("Before")); } //如果存在interceptor特性,调用类字段的invoke方法 if (interceptorAttributeType != null) { //load arguments ilMethod.Emit(OpCodes.Ldarg_0); //this ilMethod.Emit(OpCodes.Ldfld, fieldInterceptor); ilMethod.Emit(OpCodes.Ldloc, impObj); ilMethod.Emit(OpCodes.Ldloc, methodName); ilMethod.Emit(OpCodes.Ldloc, parameters); // call Invoke() method of Interceptor ilMethod.Emit(OpCodes.Callvirt, interceptorAttributeType.GetMethod("Invoke")); } else { //direct call method if (method.ReturnType == typeof (void) && actionAttributeType == null) { ilMethod.Emit(OpCodes.Ldnull); } ilMethod.Emit(OpCodes.Ldloc, impObj); for (var j = 0; j < methodParameterTypes.Length; j++) { ilMethod.Emit(OpCodes.Ldarg, j + 1); } ilMethod.Emit(OpCodes.Callvirt, impType.GetMethod(method.Name)); //box if (actionAttributeType != null) { if (method.ReturnType != typeof (void)) ilMethod.Emit(OpCodes.Box, method.ReturnType); else ilMethod.Emit(OpCodes.Ldnull); } } //如果action特性存在,则把结果包装成object传给after方法 //dynamic proxy action after if (actionAttributeType != null) { ilMethod.Emit(OpCodes.Stloc, result); //load arguments ilMethod.Emit(OpCodes.Ldloc, actionAttributeObj); ilMethod.Emit(OpCodes.Ldloc, methodName); ilMethod.Emit(OpCodes.Ldloc, result); ilMethod.Emit(OpCodes.Call, actionAttributeType.GetMethod("After")); } // pop the stack if return void //void类型,直接返回结果 if (method.ReturnType == typeof (void)) { ilMethod.Emit(OpCodes.Pop); } else { //unbox,if direct invoke,no box if (fieldInterceptor != null || actionAttributeObj != null) { if (method.ReturnType.IsValueType)//值类型=拆箱 ilMethod.Emit(OpCodes.Unbox_Any, method.ReturnType); else ilMethod.Emit(OpCodes.Castclass, method.ReturnType); //引用类型,则需要类型转换 } } // complete ilMethod.Emit(OpCodes.Ret); } } }
class Program { static void Main(string[] args) { IBusinessClass instance = DynamicProxy.CreateProxyOfRealize<IBusinessClass, Business>(); instance.add(); Console.ReadKey(); } }
先输出action类的before方法 ,再调用Interceptor特性的before方法 。出是先interceptor,后action
==>action方法特性在最外层, Intercepror特性类在最方法的最内层。
ActionAttribute before,method:add InterceptorAttribute before invokc add method InterceptorAttribute after invoke ActionAttribute after,method:add
AOP从静态代理到动态代理(Emit实现)详解
https://www.jb51.net/article/147526.htm