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/

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

  1. ASP.NET MVC中的cshtml页面中的下拉框的使用

    ASP.NET MVC中的cshtml页面中的下拉框的使用 用上@Html.DropDownList 先记下来..以做备忘...

  2. EF+LINQ事物处理 C# 使用NLog记录日志入门操作 ASP.NET MVC多语言 仿微软网站效果(转) 详解C#特性和反射(一) c# API接受图片文件以Base64格式上传图片 .NET读取json数据并绑定到对象

    EF+LINQ事物处理   在使用EF的情况下,怎么进行事务的处理,来减少数据操作时的失误,比如重复插入数据等等这些问题,这都是经常会遇到的一些问题 但是如果是我有多个站点,然后存在同类型的角色去操作 ...

  3. asp.net MVC 应用程序的生命周期(下)

    看看上面的UrlRoutingModule源码里面是怎么实现Init方法的,Init()方法里面我标注红色的地方: application.PostResolveRequestCache += new ...

  4. 【转】asp.net mvc(模式)和三层架构(BLL、DAL、Model)的联系与区别

    原文地址:http://blog.csdn.net/luoyeyu1989/article/details/8275866 首先,MVC和三层架构,是不一样的. 三层架构中,DAL(数据访问层).BL ...

  5. asp.net mvc(模式)和三层架构(BLL、DAL、Model)的联系与区别 转载自:http://blog.csdn.net/luoyeyu1989/article/details/8275866

    首先,MVC和三层架构,是不一样的. 三层架构中,DAL(数据访问层).BLL(业务逻辑层).WEB层各司其职,意在职责分离. MVC是 Model-View-Controller,严格说这三个加起来 ...

  6. asp.net mvc 之旅—— 第二站 窥探Controller下的各种Result

    平时我们在Action中编码的时候,我们都知道所有的Action返回值类型都是ActionResult,并且我们的返回值也是各种奇葩,比如:Json(),Content(), View()等等...当 ...

  7. asp.net MVC实现文章的上一篇下一篇

    由于这个东西的原理没有什么难的(只是实现的时候有少量的坑),故直接上代码以便查阅.另:本文给出的Action附送了点击量统计. public ActionResult SingleNews(int? ...

  8. asp.net MVC实现文章的“上一篇下一篇”

    由于这个东西的原理没有什么难的(只是实现的时候有少量的坑),故直接上代码以便查阅.另:本文给出的Action附送了点击量统计. public ActionResult SingleNews(int? ...

  9. 如何建立一个完整的游戏AI

    http://blog.friskit.me/2012/04/how-to-build-a-perfect-game-ai/ 人工智能(Artificial Intelligence)在游戏中使用已经 ...

随机推荐

  1. fsl的feat软件分包使用笔记

    introduction: 1. feat 是一种基于模型的fmri数据分析方法. 2. feat 首先使用顺手,至少看起来,比spm漂亮多了. feat是按照正常人的使用方法去设计的. spm 由于 ...

  2. Android-获取外置SDcard路径

    Android手机支持SDcard.目前很多手机厂商把SDcard集成到手机中,当然有的手机同时也支持可插拔的SDcard.这就有了内置SDcard和位置SDcard之分.当手机同时支持内置和外置SD ...

  3. 转载--Linux命令top动态观察程序的变化

    转载:http://www.cnblogs.com/allen8807/archive/2010/11/10/1874001.html top:动态观察程序的变化 [root@linux ~]# to ...

  4. 【转】QTP书写程序技巧

    一.添加固定注释 新建一TXT文档,将要添加的注释写在文档中 将文档名改为:ActionTemplate.mst 将文件放到QTP安装目录的dat文件夹中 设置好后,在QTP中每次新建一个测试就会自动 ...

  5. ElasticSearch elasticsearch-servicewrapper 在linux上的安装部署全程记录

    原文地址:http://www.cnblogs.com/tianjixiaoying/p/4316011.html 由于项目需求,需要在linux平台搭建一套ES服务.在搭建过程中,遇到各种各样的问题 ...

  6. POJ 3666 Making the Grade (DP滚动数组)

    题意:农夫约翰想修一条尽量平缓的路,路的每一段海拔是A[i],修理后是B[i],花费|A[i] – B[i]|,求最小花费.(数据有问题,代码只是单调递增的情况) #include <stdio ...

  7. HDU 1078 FatMouse and Cheese (记忆化搜索+dp)

    详见代码 #include <iostream> #include <cstdio> #include <cstdlib> #include <memory. ...

  8. (转载)反编译android的apk文件步骤

    下面的方法我已经尝试过,完全可以成功,重点的步骤我在这里说一下 1.必须要有java环境,记得配置好环境变量 2.如果只查看class中的函数文件,只需要下载dex2jar和jd-gui 3.下载地址 ...

  9. python-面向对象(一)——开篇基础

    面向对象编程(Object Oriented Programming,OOP,面向对象程序设计) 一.创建类和对象 面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现, ...

  10. linux下如何执行PHP脚本

    Linux 下如何直接执行 php 脚本? 下面是部分 php 命令行参数. 用法 php [-q] [-h] [-s] [-v] [-i] [-f ] | { [args...]} -q 安静模式, ...