• 建立一个方法的attribute,可以放在任意方法上,可以自动记录方法出错时的信息,就不用写try 。。cacth. 【注意】 不是在asp.net MVC下,是在普通三层结构下写的的特性。


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace ConsoleApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                TestA test = DynamicProxy.Create<TestA>();
                int result = test.TestMethod(1, 2);
    
                Console.WriteLine(result);
    
                Console.WriteLine("done...");
                Console.ReadLine();
            }
        }
    
        public class TestA
        {
            [Log]
            public virtual int TestMethod(int a, int b)
            {
                return a + b;
            }
        }
    
        public class AspectContext
        {
            public object[] ParameterArgs { get; set; }
        }
    
        public abstract class AspectAttribute : Attribute
        {
            public abstract void BeforeInvoke(AspectContext cxt);
    
            public abstract void AfterInvoke(AspectContext cxt);
        }
    
        public class LogAttribute : AspectAttribute
        {
            public override void BeforeInvoke(AspectContext cxt)
            {
                if (cxt != null && cxt.ParameterArgs != null)
                {
                    foreach (object item in cxt.ParameterArgs)
                        Console.WriteLine(item);
                }
    
                Console.WriteLine("a");
            }
    
            public override void AfterInvoke(AspectContext cxt)
            {
                Console.WriteLine("b");
            }
        }
    
        public class DynamicProxy
        {
            private static Dictionary<string, object> func_dic = new Dictionary<string, object>();
    
            public static T Create<T>()
            {
                return Create<T>(typeof(T));
            }
    
            public static T Create<T>(Type srcType)
            {
                object obj = null;
                if (!func_dic.TryGetValue(srcType.FullName, out obj))
                {
                    lock (func_dic)
                    {
                        if (!func_dic.TryGetValue(srcType.FullName, out obj))
                        {
                            Type type = CreateProxyType(srcType);
                            obj = CreateFunc<T>(type);
                            func_dic.Add(srcType.FullName, obj);
                        }
                    }
                }
    
                //通过代理创建实例
                Func<T> func = obj as Func<T>;
                if (func == null)
                    throw new Exception("unknown exception");
    
                return func();  
            }
    
            //创建类对象的代理
            private static Func<T> CreateFunc<T>(Type type)
            {
                DynamicMethod method = new DynamicMethod("", typeof(T), null);
                var il = method.GetILGenerator();
    
                ConstructorInfo info = type.GetConstructor(Type.EmptyTypes);
                if (info == null) return null;
    
                il.Emit(OpCodes.Newobj, info);
                il.Emit(OpCodes.Ret);
    
                return method.CreateDelegate(typeof(Func<T>)) as Func<T>;
            }
    
            private static Type CreateProxyType(Type srcType)
            {
                AssemblyName assemblyName = new AssemblyName(srcType.Name + "_Aop_Assmely");
                AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
                ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(srcType.Name + "_Aop_Module");
    
                string typeName = srcType.Name + "_Aop";
                TypeAttributes attr = TypeAttributes.Class | TypeAttributes.Public;
                TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, attr, srcType, Type.EmptyTypes);
    
                MethodInfo[] methods = srcType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
                foreach (MethodInfo method in methods)
                    OverrideMethods(typeBuilder, method);
    
                return typeBuilder.CreateType();
            }
    
            private static void OverrideMethods(TypeBuilder tb, MethodInfo method)
            {
                if (!method.IsPublic|| !method.IsVirtual || IsObjectMethod(method)) return;
    
                Type[] paramTypes = GetParameterTypes(method);
                MethodAttributes attr = MethodAttributes.Public | MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.Virtual;
                MethodBuilder mb = tb.DefineMethod(method.Name, attr, method.ReturnType, paramTypes);
    
                LocalBuilder result = null;
                ILGenerator il = mb.GetILGenerator();
                bool is_void = method.ReturnType != typeof(void);
    
                if (is_void == false)
                    result = il.DeclareLocal(method.ReturnType);
    
                object[] attrs = method.GetCustomAttributes(typeof(AspectAttribute), false);
                if (attrs != null)
                {
                    //初始化所有当前方法用到的参数object[]
                    CreateLocalParameterArr(il, paramTypes);
    
                    //初始化AspectContext
                    Type ctxType = typeof(AspectContext);
                    ConstructorInfo info = ctxType.GetConstructor(Type.EmptyTypes);
    
                    var ctx = il.DeclareLocal(ctxType);
                    il.Emit(OpCodes.Newobj, info);
                    il.Emit(OpCodes.Stloc, ctx);
    
                    //给AspectContext的参数值属性ParameterArgs赋值
                    var propMethod = ctxType.GetMethod("set_ParameterArgs");
                    il.Emit(OpCodes.Ldloc, ctx);
                    il.Emit(OpCodes.Ldloc_0);
                    il.Emit(OpCodes.Call, propMethod);
    
                    int m = attrs.Length;
                    LocalBuilder[] lbs = new LocalBuilder[m];
                    MethodInfo[] endInvokeMethods = new MethodInfo[m];
    
                    //初始化标记的横切对象,并调用横切对象的BeforeInvoke方法
                    for (int i = 0; i < m; i++)
                    {
                        var tmpType = attrs[i].GetType();
                        var aspect = il.DeclareLocal(tmpType);
                        ConstructorInfo tmpInfo = tmpType.GetConstructor(Type.EmptyTypes);
    
                        il.Emit(OpCodes.Newobj, tmpInfo);
                        il.Emit(OpCodes.Stloc, aspect);
    
                        var before_invoke_method = tmpType.GetMethod("BeforeInvoke");
                        endInvokeMethods[i] = tmpType.GetMethod("AfterInvoke");
    
                        il.Emit(OpCodes.Ldloc, aspect);
                        il.Emit(OpCodes.Ldloc, ctx);
                        il.Emit(OpCodes.Callvirt, before_invoke_method);
                        il.Emit(OpCodes.Nop);
    
                        lbs[i] = aspect;
                    }
    
                    //类对象,参数值依次入栈
                    for (int i = 0; i <= paramTypes.Length; i++)
                        il.Emit(OpCodes.Ldarg, i);
    
                    //调用基类的方法
                    il.Emit(OpCodes.Call, method);
    
                    //如果有返回值,保存返回值到局部变量
                    if (is_void == false)
                        il.Emit(OpCodes.Stloc, result);
    
                    //调用横切对象的AfterInvoke方法
                    for (int i = 0; i < m; i++)
                    {
                        il.Emit(OpCodes.Ldloc, lbs[i]);
                        il.Emit(OpCodes.Ldloc, ctx);
                        il.Emit(OpCodes.Callvirt, endInvokeMethods[i]);
                        il.Emit(OpCodes.Nop);
                    }
    
                    //如果有返回值,则把返回值压栈
                    if (is_void == false)
                        il.Emit(OpCodes.Ldloc, result);
    
                    //返回
                    il.Emit(OpCodes.Ret);
                }
            }
    
            private static void CreateLocalParameterArr(ILGenerator il, Type[] paramTypes)
            {
                il.DeclareLocal(typeof(object[]));
                il.Emit(OpCodes.Ldc_I4, paramTypes.Length);
                il.Emit(OpCodes.Newarr, typeof(object));
                il.Emit(OpCodes.Stloc_0);
    
                for (int i = 0; i < paramTypes.Length; i++)
                {
                    il.Emit(OpCodes.Ldloc_0);
                    il.Emit(OpCodes.Ldc_I4, i);
                    il.Emit(OpCodes.Ldarg, i + 1);
                    if (paramTypes[i].IsValueType)
                        il.Emit(OpCodes.Box, paramTypes[i]);
                    il.Emit(OpCodes.Stelem_Ref);
                }
            }
    
            private static Type[] GetParameterTypes(MethodInfo method)
            {
                var paramInfos = method.GetParameters();
                int len = paramInfos.Length;
                Type[] paramTypes = new Type[len];
                for (int i = 0; i < len; i++)
                    paramTypes[i] = paramInfos[i].ParameterType;
    
                return paramTypes;
            }
    
            //判断是否是基类Object的虚方法
            private static bool IsObjectMethod(MethodInfo info)
            {
                string[] arr = new string[] { "ToString", "GetType", "GetHashCode", "Equals" };
                return arr.Contains(info.Name);
            }
        }
    }
    

    例:AttrbuteTest]//这个特性是用来捕捉方法的异常,并记录到日志
    public void Test()
    {
        string str = "test";
        int i = int.Parse(str);
    } 

    原文出自:http://q.cnblogs.com/q/57373/

  • 相关阅读:
    js触摸屏案例
    Docker
    Docker 镜像加速
    Docker 命令大全
    linux gpasswd
    Docker基础教程
    PHP输出毫秒时间戳
    PHP Variable handling 函数
    Partition Array by Odd and Even
    Median
  • 原文地址:https://www.cnblogs.com/bobo-pcb/p/3445877.html
Copyright © 2020-2023  润新知