先说下场景,C#中为什么要使用Aop,而我又是在哪里使用Aop?


本人只是想拦截实体类的Set的方法,然后在Set之前,调用一下其它方法,把值赋给另一个对象。
而我做的都是在实体类的基类里处理:
比如:
public class OrmBase
让所有继承这个基类的实体类都具有Orm操作功能,再加上一个小小特殊的要求处理,属性Set时,需要对另一对象赋值。
如果说,我这样实现:在OrmBase中可以提供方法,让所有的子类的属性都这样操作:
public class Users:OrmBase
{
public int _ID;
public int ID 
{
get;
set
{
base.SetXX(value);
}
}

不过每个实体都这样写,虽然是啥没问题,不过能简化的还是简化。
在能追求简洁的世界里,当然更喜欢简洁的写法如:

public int ID {get;set;}

因此,直接在基类里直接拦截子类set方法,在里面直接调用SetXX就搞定了,如何实现呢?又花了一天的时间查资料研究学习并实现。
为此,要拦截,就得折腾Aop:
传统的Aop使用RealProxy,使用非常简单,但是被忽悠的非常复杂,下面:
1:在要拦截的类头上加个属性标识:
[AopAttribute]
public class OrmBase

OK,在基类里加一个,这样所有子类也算被附加了,加上一个标识,就可以被拦截了,那这个AopAttribute属性是啥?看下面
2:AopAttribute继承代理属性标识类,用来挂在要拦截的类的头上:
class AopAttribute : ProxyAttribute
{
public override MarshalByRefObject CreateInstance(Type serverType)
{
AopProxy realProxy = new AopProxy(serverType);
return realProxy.GetTransparentProxy() as MarshalByRefObject;
}
}

看,里面就两行,非常简单,中间调用了继承RealProxy的AopProxy类,AopProxy是什么,怎么出来的?看下面
3:AopProxy类,就是拦截的消息处理,先上个简单版,免的大伙看不懂:
class AopProxy : RealProxy
{
public AopProxy(Type serverType)
: base(serverType)
{
}
public override IMessage Invoke(IMessage msg)
{
//消息拦截之后,就会执行这里的方法。
}
}

OK,简单吧,就这么两个类,就可以实现拦截了,不过重点就是这里拦截之后的代码,稍为复杂点,一般照抄就行了,拦截的代码如下:
if (msg is IConstructionCallMessage) // 如果是构造函数,按原来的方式返回即可。
{
IConstructionCallMessage constructCallMsg = msg as IConstructionCallMessage;
IConstructionReturnMessage constructionReturnMessage = this.InitializeServerObject((IConstructionCallMessage)msg);
RealProxy.SetStubData(this, constructionReturnMessage.ReturnValue);
return constructionReturnMessage;
}
else if (msg is IMethodCallMessage) //如果是方法调用(属性也是方法调用的一种)
{
IMethodCallMessage callMsg = msg as IMethodCallMessage;
object[] args = callMsg.Args;
IMessage message;
try
{
if (callMsg.MethodName.StartsWith("set_") && args.Length == 1)
{
//这里检测到是set方法,然后应怎么调用对象的其它方法呢?
}
object o = callMsg.MethodBase.Invoke(GetUnwrappedServer(), args);
message = new ReturnMessage(o, args, args.Length, callMsg.LogicalCallContext, callMsg);
}
catch (Exception e)
{
message = new ReturnMessage(e, callMsg);
}
return message;
}
return msg;

为了调用原始对象的其它方法,我花了近一天的时间查资料,可惜网络上并没有相应的信息,多数的人应用,都是引向一个其它方法(一个不需要调用原始对象的方法)
目前网络上Aop信息太少,C#的更少,关于如何获取原始对象,然后调用原始对象的,找不到一篇相关文章,我特纠结。 
于是,我按传统方式,想尽办法的想获取到原始对象,再调用,经过九九八十一招,还是失败了。
(一开始是想:通过反射从类型再创建一个实体这种不靠谱的尝试: 造成死循环,每次new拦截,在拦截里又new)
中间省一大堆......痛苦的经历和尝试.......
只要用心想,方法总有的,最终还是被我发现了:
1:获取要调用的方法:
在构造函数中,根据传进来的serverType,获取到SetXX的方法MethodInfo:
method = serverType.GetMethod("SetXX", BindingFlags.NonPublic | BindingFlags.Instance);
2:在拦截方法中调用:
if (callMsg.MethodName.StartsWith("set_") && args.Length == 1)
{
method.Invoke(GetUnwrappedServer(), new object[] { callMsg.MethodName.Substring(4), args[0] });//对属性进行调用
}

过程很复杂,尝试过N百种方式,结果很简单,分享很重要!
为此,解决了ORM对子类的属性拦截,并实现了在属性赋值时调用实例其它方法。
     本文转自cyq1162 51CTO博客,原文链接:http://blog.51cto.com/cyq1162/882782,如需转载请自行联系原作者

C# Aop简单扫盲及ORM实体类属性拦截示例相关推荐

  1. 如何配置数据库带有下划线字段对应Java实体类属性(驼峰命名)

    一般开发中,数据库字段设计推荐使用下划线(u_name),Java实体类属性使用驼峰命名(uName),为了能使数据库字段与Java实体类属性一一映射,需要做一下的配置,这里我用的是spring bo ...

  2. 【转】MyBatis学习总结(四)——解决字段名与实体类属性名不相同的冲突

    [转]MyBatis学习总结(四)--解决字段名与实体类属性名不相同的冲突 在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的,下面来演示一下这种情况下的如何解决字段名与实体 ...

  3. MyBatis学习总结(四)——解决字段名与实体类属性名不相同的冲突

    2019独角兽企业重金招聘Python工程师标准>>> 一.准备演示需要使用的表和数据 CREATE TABLE orders(order_id INT PRIMARY KEY AU ...

  4. 发布一个实体类属性生成小工具,给开发加点料

    做了很久的代码生成工具,基本上都是基于表生成实体类属性的,把数据库表的信息拿出来,然后之乎者也后生成一个标准的实体类,包含字段.属性.描述等东西. 是基于整个数据库生成整个框架代码的工具,如我的代码生 ...

  5. Mybatis解决字段名与实体类属性名不相同的冲突

    在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的,下面来演示一下这种情况下的如何解决字段名与实体类属性名不相同的冲突. 一.准备演示需要使用的表和数据 CREATE TAB ...

  6. MyBatis Plus——忽略某个实体类属性和数据库表字段之间的映射关系

    问题描述 在开发中可能会遇到MyBatis-Plus使用实体类属性进行SQL操作,但是不用存到数据库中去查找,这时候我们的实体中有这个属性,但是数据库的表中没有这个字段(即:实体类属性非数据库表字段) ...

  7. 【MyBatis】sql列名与实体类属性名不同的解决方式

    sql列名与Java实体类属性名不同的解决方式 例如: 数据库 CREATE TABLE orders(order_id INT PRIMARY KEY AUTO_INCREMENT,order_no ...

  8. MyBatis学习总结(4)——解决字段名与实体类属性名不相同的冲突

    一.准备演示需要使用的表和数据 CREATE TABLE orders(order_id INT PRIMARY KEY AUTO_INCREMENT,order_no VARCHAR(20), or ...

  9. Mybatis中resultMap的作用-解决实体类属性名和数据库字段不一致

    解决实体类属性名和数据库字段不一致 转载于:https://www.cnblogs.com/mww-NOTCOPY/p/10950712.html

最新文章

  1. 滴滴重磅发布:KDD2018大会187页人工智能+交通教程
  2. OpenCV2:应用篇 QT+OpenCV实现图片编辑器
  3. 熟悉HTML CSS布局模型
  4. java守护线程的特性
  5. Qt修炼手册1_溢美之词和Designer设计
  6. 商品审核网页界面_商品模块数据库表解析(二)
  7. react redux 相关技术
  8. 【CodeForces - 227C】Flying Saucer Segments (思维)
  9. SSD( Single Shot MultiBox Detector)关键源码解析
  10. 升级成员服务器-从Windows 2012升级到2016案例之2
  11. 盒子不显示工会与服务器,DNF天空盒子找不到怎么办 dnf新版本活动防坑指攻略...
  12. 将人民币大写金额格式转为数字金额格式C#代码
  13. EUI插件服务器负载显示不兼容,EUI - 魔兽世界最贴心的插件
  14. temp在python里的意思_python temp是什么
  15. USACO 2021 January Contest, BronzeProblem 2. Even More Odd Photos题解
  16. LiveData详细分析
  17. 预测移动用户人口属性的Kaggle竞赛作品解析
  18. vim tutorial 101 hacks(三)
  19. 计算机算法的控制结构顺序结构,第3章 算法与控制结构.pdf
  20. windows服务器双网卡修改默认路由,windows下双网卡双网关的设置

热门文章

  1. List 如何根据对象的属性去重?Java 8 轻松搞定!
  2. 一款高颜值的MySQL管理工具:Sequel Pro
  3. 公司规定所有接口都用 POST请求?
  4. Alibaba Sentinel限流功能
  5. 分页场景(limit,offset)为什么会慢?
  6. 非常有必要了解的Springboot启动扩展点
  7. 数据库分库分表,何时分?怎样分?
  8. CMU赵越 关于异常检测的分享!
  9. Datawhale入选DataFountain优秀组织
  10. GitHub 2021年度报告发布:中国755万开发者排名全球第二!