【分享】纯手工打造Emit,实现AOP,附源码下载

NqIceCoffee 2011-07-14 02:44:58
加精
比较喜欢Emit,所以就胡乱写点东西。这个是新鲜出炉的,分享给大家

AOP具体的原理我就不多讲了,大家可以查查资料,我这里用的【继承+重写+动态植入IL代码】

好了,废话少说,下载地址如下

http://download.csdn.net/source/3441835

在附上一个代码片段,嘿嘿。欢迎大虾拍砖

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);
}
}
...全文
2959 119 打赏 收藏 转发到动态 举报
写回复
用AI写文章
119 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
楼主给我一个qq,交流一下
吴说扒道 2011-09-02
  • 打赏
  • 举报
回复
谢谢,正好在看emit的东西。
G.spring 2011-08-15
  • 打赏
  • 举报
回复
感谢分享。
Bind 2011-08-15
  • 打赏
  • 举报
回复
嘿嘿 之前用entlib的piab做wcf服务端的方法调用权限验证, 不过总觉得有些重量级

楼主这个轻量级的应用非常喜欢, 顶楼主. 谢谢楼主.
小阳 2011-07-29
  • 打赏
  • 举报
回复
支持源码!帮顶!
NqIceCoffee 2011-07-29
  • 打赏
  • 举报
回复
奇怪啊,没人回复,咋无缘无故的又跑首页来了
lisweden 2011-07-26
  • 打赏
  • 举报
回复
[Quote=引用 60 楼 ojlovecd 的回复:]

嗯,上次看过楼主发的Emit的代码,确实挺不错的,也为那个帖子如此冷清替楼主感到可惜
[/Quote]

顶一个,楼主所发的,正是最近要学习的
qydvip 2011-07-25
  • 打赏
  • 举报
回复
看不懂 不过楼主还是很厉害的 呵呵
lookmai 2011-07-25
  • 打赏
  • 举报
回复
楼主,赞一个,此类方法也能用,解决了我的难题。我用反射难以实现。
public List<T> GetList<T>(int ID) where T : class, new()
huyong19781 2011-07-24
  • 打赏
  • 举报
回复
Emit主要适用什么场合呢
Delta 2011-07-24
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 indusl 的回复:]
好吧,我学习下
[/Quote]......
SK_Aqi 2011-07-23
  • 打赏
  • 举报
回复
mark
小堇 2011-07-23
  • 打赏
  • 举报
回复
帮顶~~!
冬日 2011-07-23
  • 打赏
  • 举报
回复
很好很NB,就是还没看懂,不过既然是推荐贴,我收藏起来看看
wenqiang68868 2011-07-23
  • 打赏
  • 举报
回复
路过。。。
juntor 2011-07-22
  • 打赏
  • 举报
回复
顶楼主
1 1 2011-07-22
  • 打赏
  • 举报
回复
不懂,支持个吧
感动呀 2011-07-22
  • 打赏
  • 举报
回复
看不太懂啊,希望楼主给个文档和需要的一些准备工作啊, 直接看到一段代码,也没有情景 , 不知道怎么入手 , 怎么用法,我的QQ:308110228 , 3q
NqIceCoffee 2011-07-22
  • 打赏
  • 举报
回复
[Quote=引用 110 楼 zzz9413 的回复:]
代码没有注释,很多看不懂。楼主能否发个注释版本的代码
100分我都出
[/Quote]

最关键的OverrideMethods方法已经添加注释,在细就是一些指令了,这些网上都能查到的
zzz9413 2011-07-22
  • 打赏
  • 举报
回复
代码没有注释,很多看不懂。楼主能否发个注释版本的代码
100分我都出
加载更多回复(99)

62,234

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧