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的更多相关文章

  1. C#.NET利用ContextBoundObject和Attribute实现AOP技术--AOP事务实现例子

    我前两天看见同事用写了用AOP技术实现缓存的方案,于是好奇看了一下这是怎么实现的.原来是用了.NET中的一个类ContextBoundObject和Attribute相关技术.其实个类在.NET Fr ...

  2. 利用Attribute实现Aop

    Aop“面向切面编程”,与OOP“面向对象编程”一样是一种编程思路.个人理解:在不改变原有逻辑的基础上,注入其他行为. 基础代码(仿MVC拦截器实现) namespace HGL.Toolkit.Ao ...

  3. 从Unity中的Attribute到AOP(七)

    本章我们将依然讲解Unity中的Attribute,继续命名空间在UnityEngine里的. PropertyAttribute,这个特性主要来控制变量或者类在Inspector里面的显示方式.和P ...

  4. 从Unity中的Attribute到AOP(六)

    本文将重点对Unity剩下常用的Attribute进行讲解,其他不常用的Attribute各位可以自行去官方文档查阅. 首先是UnityEngine命名空间下的. ColorUsage,这个主要作用于 ...

  5. 从Unity中的Attribute到AOP(五)

    今天主要来讲一下Unity中带Menu的Attribute. 首先是AddComponentMenu.这是UnityEngine命名空间下的一个Attribute. 按照官方文档的说法,会在Compo ...

  6. 从Unity中的Attribute到AOP(四)

    本篇我们将逐一讲解Unity中经常使用的Attribute(Unity对应的文档版本为2018.1b). 首先是Serializable,SerializeField以及NonSerialized,H ...

  7. 从Unity中的Attribute到AOP(三)

    上一篇我们对系统的Attributes进行了MSIL代码的查看,了解到了其本质就是一个类的构造函数.本章我们将编写自己的Attributes. 首先我们定义书的属性代码,如下: [AttributeU ...

  8. 从Unity中的Attribute到AOP(二)

    上一篇文章我们初步了解了一下Attributes的含义,并且使用系统自带的Attributes写了点代码.在进一步解剖我们的代码之前,我觉得有个概念可能需要巩固一下:什么是元数据? 我们知道C#代码会 ...

  9. 从Unity中的Attribute到AOP(一)

    首先来看一下微软官方对Attributes(C#)的定义: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/conce ...

随机推荐

  1. 使用conda部署jupyterhub以及ladp验证的安装

    前提:机器安装有conda环境 官方文档:http://jupyterhub.readthedocs.io/en/stable/quickstart.html 1.安装conda3 jupyterhu ...

  2. Cesium截图功能

    首先安装  canvas2image npm intsall canvas2image --save 因为项目基于vue,所以需要在canvas2image的最后面 加上 export default ...

  3. django 框架下的路由分发

  4. 轻松解决U盘拷贝文件时提示文件过大问题

    现在的高科技时代生活中,u盘的使用已经是许多从事电脑it行业的人每天都必须要用到的用具.可以在一台电脑上使用u盘拷贝文件到另外一台电脑上进行使用,加上它的身材小巧,非常方便我们随身携带到任何地方进行使 ...

  5. 【C#、阿里云、Tomcat、XP系统】c#下使用.NET4.0中HttpWebRequest访问Tomcat中HTTPS项目时,在XP系统中超时

    情景: 1.使用Java开发的Web项目,部署在服务器Tomcat中 2.项目使用HTTPS,使用阿里云的PFX证书 阿里云推荐Tomcat配置如下 <Connector port=" ...

  6. windows2003 disk mirror failed redundency

    操作前請確認 mirror 磁盤已備份 windows2003 disk mirror failed redundency時,offline + online並不可以自動修復. 需要offline f ...

  7. 启发式分治:2019牛客多校第三场 G题 Removing Stones

    问题可以转换为求有多少个区间数字的总和除2向下取整大于等于最大值.或者解释为有多少个区间数字的总和大于等于最大值的两倍(但是若区间数字总和为奇数,需要算作减1) 启发式分治: 首先按最大值位置分治,遍 ...

  8. Notepad++ 连接 FTP 实现编辑 Linux文件

    下载并安装插件 github 下载 :https://github.com/ashkulz/NppFTP/releases/ 安装过程 将下载后解压的文件夹中的 NppFTP.dll 文件,拷贝到 n ...

  9. Android 将drawable下的图片转换成bitmap、Drawable

    将drawable下的图片转换成bitmap . Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xxx ...

  10. mysql三种连接方式

    sql四种连接方式demo: 表a 表b a.id与b.parent_id有关系 1.内连接:SELECT a.*,b.* from a INNER JOIN b ON a.id=b.parent_i ...