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. Android-获取外置SDcard路径

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

  2. POJ -- 2436

    Disease Management Description Alas! A set of D (1 <= D <= 15) diseases (numbered 1..D) is run ...

  3. Power Strings

    Power Strings TimeLimit: 1 Second   MemoryLimit: 32 Megabyte Totalsubmit: 1791   Accepted: 528 Descr ...

  4. Unity3d BTDF实时折射模拟有粗糙度的半透明物体

    折射的原理是运用BTDF的一个球形高斯近似 需要考虑折射光的来源,一般会想到用环境贴图(IBL)或者grab texture,但是折射光不全都来自一个平面,所以选择环境贴图来作为折射光.这个效果主要是 ...

  5. RHEL7下安装使用TensorFlow和kcws

    0.安装依赖包 #用pip安装python科学计算库numpy,sklearn,scipysu - wget http://dl.fedoraproject.org/pub/epel/7/x86_64 ...

  6. [基础] Loss function (二)

    Loss function = Loss term(误差项) + Regularization term(正则项),上次写的是误差项,这次正则项. 正则项的解释没那么直观,需要知道不适定问题,在经典的 ...

  7. crontab command not found

    在服务器上运行 crontab -e编辑定时任务 结果提示 command not found命令找不到,这就说明没安装crontab 由于 完整操作如下: [root@iZ11pvsxisqZ /] ...

  8. ant+svn+tomcat实现项目自动部署

    因工作需要,研究并实现了 ant+svn+tomcat实现项目自动部署,其中参考了下面文章:http://www.cnblogs.com/taoweiji/p/3700915.html jar包需要e ...

  9. HttpClient4.5.2 连接池原理及注意事项

    随着微服务的流行,服务之间的http调用越来越多,遇到的问题也比较多,写这边文章的目的也是将自己遇到的坑和解决方案跟大家分享 一.为什么要用Http连接池 1.降低延迟:如果不采用连接池,每次连接发起 ...

  10. ASP.NET MVC- MvcPager

    本文目标 一.能够使用MvcPager进行分页 本文目录 一.MvcPager控件的简单使用 二.C#扩展方法 一.MvcPager控件的简单使用 1.添加MvcPager.dll的引用[下载] 2. ...