Attribute 实现Aop
1、先定义一个 拦截属性 AopAttribute
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ZH.Aop
{
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Activation;
[AttributeUsage(AttributeTargets.Class)]
public class AopAttribute : Attribute, IContextAttribute
{
public void GetPropertiesForNewContext(IConstructionCallMessage msg)
{
msg.ContextProperties.Add(new AOPProperty());
}
public bool IsContextOK(Context ctx, IConstructionCallMessage msg)
{
AOPProperty aOPProperty = ctx.GetProperty("Aop") as AOPProperty;
return aOPProperty!=null;
}
}
}
2 实现 ContextProperty, IContributeServerContextSink
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ZH.Aop
{
using System.Runtime.Remoting.Contexts;
using System.Runtime.Remoting.Messaging;
internal class AOPProperty : IContextProperty, IContributeServerContextSink
{
public string Name => "Aop"; public AOPProperty()
{
Console.WriteLine(nameof(AOPProperty));
}
public void Freeze(Context newContext)
{ }
public bool IsNewContextOK(Context newCtx)
{
var result = newCtx.GetProperty("Aop");
return result != null;
} public IMessageSink GetServerContextSink(IMessageSink nextSink)
{
Aspect aspect = new Aspect(nextSink);
return aspect;
}
}
}
3、 实现事件 执行类(主要) Aspect
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ZH.Aop
{
using System.Runtime.Remoting.Messaging;
using System.Dynamic;
using ZH.Aop.AopListener;
using ZH.Aop.ArgsModel;
internal class Aspect : IMessageSink
{
private IMessageSink nextSink = null;
public Aspect(IMessageSink messageSink)
{
nextSink = messageSink;
}
public IMessageSink NextSink => nextSink; public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
{
return null;
}
/// <summary>
/// 处理事件
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public IMessage SyncProcessMessage(IMessage msg)
{ // 方法执行之前】
dynamic defaultValue = new ExpandoObject();
var callMsg = msg as IMethodCallMessage;
AopEventArgs aopEventArgs = new AopEventArgs();
aopEventArgs.StartTime = DateTime.Now;
aopEventArgs.MethodName = callMsg.MethodName;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
MethodListen.GetInstance().BeginMethod(aopEventArgs); // 如果不是构造函数
if (!callMsg.MethodBase.IsConstructor)
{
defaultValue = ((System.Reflection.MethodInfo)(callMsg.MethodBase)).ReturnParameter.DefaultValue;
// 实例 如果方法的名称是 SetName 则放弃执行
// if (callMsg.MethodName == "SetName")
// return new ReturnMessage(defaultValue, callMsg.Args, callMsg.ArgCount, callMsg.LogicalCallContext, callMsg);
}
try
{
IMessage returnMsg = nextSink.SyncProcessMessage(msg);
stopwatch.Stop();
aopEventArgs.OperateTime = stopwatch.ElapsedMilliseconds;
aopEventArgs.EndTime = DateTime.Now;
return returnMsg;
}
catch (Exception ex)
{
aopEventArgs.Exception = ex;
throw;
}
finally
{
// 执行方法之后
MethodListen.GetInstance().AfterMethod(aopEventArgs);
}
} }
}
4 另外 监听事件的执行
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ZH.Aop.AopListener
{
using ZH.Aop.ArgsModel;
public interface IMethodListen
{
event EventHandler<AopEventArgs> OnMethodBegin;
event EventHandler<AopEventArgs> OnMethodAfter;
}
}
实现上面接口:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ZH.Aop.AopListener
{
using ZH.Aop.ArgsModel;
public class MethodListen : IMethodListen
{
public event EventHandler<AopEventArgs> OnMethodBegin;
public event EventHandler<AopEventArgs> OnMethodAfter;
private static MethodListen _methodListen = null;
public static MethodListen GetInstance()
{
if (_methodListen == null)
_methodListen = new MethodListen();
return _methodListen;
} internal void BeginMethod(AopEventArgs aopEventArgs)
{
if (OnMethodBegin != null)
{
OnMethodBegin(this, aopEventArgs);
}
}
internal void AfterMethod(AopEventArgs aopEventArgs)
{
if (OnMethodAfter != null)
{
OnMethodAfter(this, aopEventArgs);
}
}
}
}
6 参数 model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace ZH.Aop.ArgsModel
{
using System.Reflection;
public class AopEventArgs : EventArgs
{
/// <summary>
/// 方法名称
/// </summary>
public string MethodName { get; set; } /// <summary>
/// 执行时间
/// </summary>
public long OperateTime { get; set; } /// <summary>
/// 异常信息
/// </summary>
public Exception Exception { get; set; }
/// <summary>
/// 开始时间
/// </summary>
public DateTime StartTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
public DateTime EndTime { get; set; }
}
}
测试:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZH.Aop;
using ZH.Aop.AopListener;
using ZH.Aop.ArgsModel;
namespace Demo.Aop
{
class Program
{ static void Main(string[] args)
{
MethodListen methodListen = MethodListen.GetInstance();
methodListen.OnMethodBegin += new EventHandler<AopEventArgs>(OnMethodBegin);
methodListen.OnMethodAfter += new EventHandler<AopEventArgs>(OnMethodAfter);
TestAop testAop = new TestAop();
for (int i=;i<;i++)
{ var s = testAop.SetName("zheng", );
}
Console.ReadLine();
}
public static void OnMethodBegin(object sender, AopEventArgs e)
{
Console.WriteLine($"开始执行--方法名称{e.MethodName} 开始时间:{e.EndTime}");
}
public static void OnMethodAfter(object sender, AopEventArgs e)
{
Console.WriteLine($"执行后--方法名称{e.MethodName} 总共时间{e.OperateTime} 结束时间:{e.EndTime}");
}
} [Aop]
public class TestAop : ContextBoundObject
{ public string SetName(string name, int age)
{
return $"{name}{age}";
} } }
Attribute 实现Aop的更多相关文章
- C#.NET利用ContextBoundObject和Attribute实现AOP技术--AOP事务实现例子
我前两天看见同事用写了用AOP技术实现缓存的方案,于是好奇看了一下这是怎么实现的.原来是用了.NET中的一个类ContextBoundObject和Attribute相关技术.其实个类在.NET Fr ...
- 利用Attribute实现Aop
Aop“面向切面编程”,与OOP“面向对象编程”一样是一种编程思路.个人理解:在不改变原有逻辑的基础上,注入其他行为. 基础代码(仿MVC拦截器实现) namespace HGL.Toolkit.Ao ...
- 从Unity中的Attribute到AOP(七)
本章我们将依然讲解Unity中的Attribute,继续命名空间在UnityEngine里的. PropertyAttribute,这个特性主要来控制变量或者类在Inspector里面的显示方式.和P ...
- 从Unity中的Attribute到AOP(六)
本文将重点对Unity剩下常用的Attribute进行讲解,其他不常用的Attribute各位可以自行去官方文档查阅. 首先是UnityEngine命名空间下的. ColorUsage,这个主要作用于 ...
- 从Unity中的Attribute到AOP(五)
今天主要来讲一下Unity中带Menu的Attribute. 首先是AddComponentMenu.这是UnityEngine命名空间下的一个Attribute. 按照官方文档的说法,会在Compo ...
- 从Unity中的Attribute到AOP(四)
本篇我们将逐一讲解Unity中经常使用的Attribute(Unity对应的文档版本为2018.1b). 首先是Serializable,SerializeField以及NonSerialized,H ...
- 从Unity中的Attribute到AOP(三)
上一篇我们对系统的Attributes进行了MSIL代码的查看,了解到了其本质就是一个类的构造函数.本章我们将编写自己的Attributes. 首先我们定义书的属性代码,如下: [AttributeU ...
- 从Unity中的Attribute到AOP(二)
上一篇文章我们初步了解了一下Attributes的含义,并且使用系统自带的Attributes写了点代码.在进一步解剖我们的代码之前,我觉得有个概念可能需要巩固一下:什么是元数据? 我们知道C#代码会 ...
- 从Unity中的Attribute到AOP(一)
首先来看一下微软官方对Attributes(C#)的定义: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/conce ...
随机推荐
- 每天一个linux命令:cat(10)
cat cat命令的用途是连接文件或标准输入并打印.这个命令常用来显示文件内容,或者将几个文件连接起来显示,或者从标准输入读取内容并显示,它常与重定向符号配合使用 注意:当文件较大时,文本在屏幕上迅速 ...
- c#处理3种json数据的方式
原文出处:http://www.jb51.net/article/48027.htm 一.C#处理简单json数据 json数据: {"result":"0", ...
- ceph 指定OSD创建pool
https://my.oschina.net/wangzilong/blog/1549690 ceph集群中允许使用混合类型的磁盘,比如一部分磁盘是SSD,一部分是STAT.如果针对某些业务小高速磁盘 ...
- Database基础(三):SQL数据导入/导出、 操作表记录、查询及匹配条件
一.SQL数据导入/导出 目标: 使用SQL语句完成下列导出.导入操作: 将/etc/passwd文件导入userdb库userlist表并给每条记录加编号 将userdb库userlist表中UID ...
- jq实现跟随鼠标点击移动的下划线效果
效果如下: 1.html代码: <div class="center-left-tap"> <a href="javascript:void (0)&q ...
- POJ 3904 (莫比乌斯反演)
Stancu likes space travels but he is a poor software developer and will never be able to buy his own ...
- 利用core_pattern实现core文件的配置和管理
参考:https://xz.aliyun.com/t/1098 这里所说的core_pattern 指的是:/proc/sys/kernel/core_pattern. 我们知道在Linux系统中,如 ...
- Centos7安装部署SonarQube7.9.1教程
0.参考文档 LTS 7.9.1 新特性:https://www.sonarqube.org/sonarqube-7-9-lts/ JDK11 下载地址: 链接:https://pan.baidu.c ...
- Rust <0>:源代码组织,Cargo 入门
Rust 源代码组织,使用配套的 Cargo 工具,其功能强大,程序员可摆脱 C/C++ 中需要自行维护 make.cmake 之类配置的工作量. 初始化一个项目: cargo new --bin h ...
- linux Jenkins搭建
安装jdk 下载jdk 解压 jdk1.8 vim /etc/profile export JAVA_HOME=/usr/local/java/jdk1.8.0_111export CLASSPA ...