建立一个方法的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)在游戏中使用已经 ...
随机推荐
- 微软开放技术发布开源 Jenkins 插件以将 Windows Azure Blob 服务用的开作存储库
发布于 2014-02-10 作者 陈 忠岳 持续集成 (CI) 的历史源远流长, 其宗旨在于软件团队在敏捷环境中不断将他们的工作整合为持续构建.管理 CI 进程的工具已存在一段时间.过去几年中 ...
- eclipse环境NDK问题汇总
1. 配置NDK路径设置 可以在cygwin中通过vim修改,也可以在windows安装目录中修改 home\<你的用户名>\.bash_profile 文件中最后添加环境变量 NDK=/ ...
- Android 解决安装Egit时Egit Mylyn和org.eclipse.team.core报错
为了让Aptana支持GitHub,需要安装Egit,但在的时候碰到两个错误,一个是关于缺少EGit Mylyn另一个是缺少org.eclipse.egit.import.feature.group. ...
- WP8模拟器需要BIOS开启虚拟化支持(转载)
在BIOS里启用hypervisor和virtualization,然后安装WP8 SDK. 如果出现“当前用户未添加到Hyper-V管理组时”, 以管理员身份运行CMD: net localgrou ...
- WebSocket学习笔记IE,IOS,Android等设备的兼容性问
WebSocket学习笔记IE,IOS,Android等设备的兼容性问 一.背景 公司最近准备将一套产品放到Andriod和IOS上面去,为了统一应用的开发方式,决定用各平台APP嵌套一个HTML5浏 ...
- Interleaving String——Leetcode
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given:s1 = ...
- 统计学习方法——P1
背景基础知识备忘 平均差 MD=(∑|xi-x'|)/n 加权平均差 A.D=(∑|xi-x'|fi)/∑fi 方差 标准差 SD=方差的平方根 分布函数: 设X是一个随机变量,x是任意实数,函数 ...
- .net常見面試題(二)
一.选择题 1. 下面叙述正确的是___C___. A.算法的执行效率与数据的存储结构无关 B.算法的空间复杂度是指算法程序中指令(或语句)的条数 C.算法的有穷性是指算法必须能在执行有限个步骤之后终 ...
- linux 双网关双IP设置
server:CentOS5.8 ip:172.16.8.11 Gateway:172.16.8.1 ip:10.120.6.78 Gateway:10.120.6.1 网卡配置: eth0 poin ...
- MySQL数据库设计复习笔记及项目实战
最近手头上有3个项目开动,其他2个都是从底层开始的,一个已经开始了一段时间的了,在小城市小团队开发的条件下,都没有专门的DBA来做数据库的设计和维护,往往都是开发人员顶上,可是看了很多的数据库的设计, ...