建立一个方法的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/
建立一个方法的attribute,可以放在任意方法上,可以自动记录方法出错时的信息,就不用写try 。。cacth. 【注意】 不是在asp.net MVC下,是在普通三层结构下写的的特性。的更多相关文章
- ASP.NET MVC中的cshtml页面中的下拉框的使用
ASP.NET MVC中的cshtml页面中的下拉框的使用 用上@Html.DropDownList 先记下来..以做备忘...
- EF+LINQ事物处理 C# 使用NLog记录日志入门操作 ASP.NET MVC多语言 仿微软网站效果(转) 详解C#特性和反射(一) c# API接受图片文件以Base64格式上传图片 .NET读取json数据并绑定到对象
EF+LINQ事物处理 在使用EF的情况下,怎么进行事务的处理,来减少数据操作时的失误,比如重复插入数据等等这些问题,这都是经常会遇到的一些问题 但是如果是我有多个站点,然后存在同类型的角色去操作 ...
- asp.net MVC 应用程序的生命周期(下)
看看上面的UrlRoutingModule源码里面是怎么实现Init方法的,Init()方法里面我标注红色的地方: application.PostResolveRequestCache += new ...
- 【转】asp.net mvc(模式)和三层架构(BLL、DAL、Model)的联系与区别
原文地址:http://blog.csdn.net/luoyeyu1989/article/details/8275866 首先,MVC和三层架构,是不一样的. 三层架构中,DAL(数据访问层).BL ...
- asp.net mvc(模式)和三层架构(BLL、DAL、Model)的联系与区别 转载自:http://blog.csdn.net/luoyeyu1989/article/details/8275866
首先,MVC和三层架构,是不一样的. 三层架构中,DAL(数据访问层).BLL(业务逻辑层).WEB层各司其职,意在职责分离. MVC是 Model-View-Controller,严格说这三个加起来 ...
- asp.net mvc 之旅—— 第二站 窥探Controller下的各种Result
平时我们在Action中编码的时候,我们都知道所有的Action返回值类型都是ActionResult,并且我们的返回值也是各种奇葩,比如:Json(),Content(), View()等等...当 ...
- asp.net MVC实现文章的上一篇下一篇
由于这个东西的原理没有什么难的(只是实现的时候有少量的坑),故直接上代码以便查阅.另:本文给出的Action附送了点击量统计. public ActionResult SingleNews(int? ...
- asp.net MVC实现文章的“上一篇下一篇”
由于这个东西的原理没有什么难的(只是实现的时候有少量的坑),故直接上代码以便查阅.另:本文给出的Action附送了点击量统计. public ActionResult SingleNews(int? ...
- 如何建立一个完整的游戏AI
http://blog.friskit.me/2012/04/how-to-build-a-perfect-game-ai/ 人工智能(Artificial Intelligence)在游戏中使用已经 ...
随机推荐
- 安装scrapy
- 迷宫城堡--HDOJ 1269(Tarjan)
迷宫城堡 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- devi into python 笔记(一)字典 列表的简单操作
模块: python中模块是很重要的概念,在模块中加入 if __name__ == "__main__": pass 会使模块应用起来更加灵活,避免出错. =========== ...
- nyoj 1036 非洲小孩【贪心区间选点】
非洲小孩 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 家住非洲的小孩,都很黑.为什么呢?第一,他们地处热带,太阳辐射严重.第二,他们不经常洗澡.(常年缺水,怎么洗 ...
- JVM performance profiling (有待整理)
Agenda memory model 3 parts: heap, permgen (method area) , thread stack(pointer, local var) heap: yo ...
- 今日又遇无法启动apache
前几天安装了.NET要用到的MSSERVER,之后apache就running none of service. 把微软的MSSERVER停用掉服务就没问题.哪部分冲突了
- Servlet文件上传(ServletFIleUpload,DiskFileItemFactory,FileItem)
1:我们学的是表单文件上传,就是在一个FORM中提交相应的信息,和之前我们的提交的注册信息之类的表单是不同的,所以要先改变一下FORM的属性,enctype="multipart/form- ...
- android开发:@SuppressLint( NewApi )
这个是android带的lint工具提示的,lint官方的说法是 Improving Your Code with lint,应该是帮助提升代码的 ,如果不想用的话,可以右键点工程,然后在androi ...
- LeetCode153:Find Minimum in Rotated Sorted Array
Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...
- 通过Navicat for MySQL远程连接的时候报错mysql 1130的解决方法
在用本地的navicat连接服务器的mysql数据库时候出现下面的问题: 解决的方法: 解决方法: 1.改表法.可能是你的帐号不允许从远程登陆,只能在localhost.这个时候只要在localhos ...