建立一个方法的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/

原文地址:https://www.cnblogs.com/bobo-pcb/p/3445877.html