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. hadoop 2.7 添加或删除datanode节点

    1.测试环境 ip 主机名 角色 10.124.147.22 hadoop1 namenode 10.124.147.23 hadoop2 namenode 10.124.147.32 hadoop3 ...

  2. pdfminer实现pdf布局分析 python (pdfminer realize layout analysis with PDF python)

    使用pdfminer实现pdf文件的布局分析 python 参考资料: https://github.com/euske/pdfminer https://stackoverflow.com/ques ...

  3. POJ 2528(线段树+离散化+特殊离散化)网上博客很少有人真正写对!!! 是POJ数据太水...

    Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral electio ...

  4. Jetson Nano系列教程0:初识Jetson Nano

    关于Jetson Nano Developer Kit Jetson nano搭载四核Cortex-A57 MPCore 处理器,采用128 核 Maxwell™  GPU.支持JetPack SDK ...

  5. 判断系统是否安装了flash插件

    方法1: uses comobj; procedure TForm1.Button1Click(Sender: TObject); var v:variant; begin v:=CreateOleO ...

  6. CompletableFuture提高你并发编程能力

    思考:如果有两个顺序执行耗时的方法,你该怎么做??? 例如: public void doHousework() { //烧水 doWater(); //扫地 doFloor(); } 没错,聪明如我 ...

  7. 仿flask写的web框架

    某大佬仿flask写的web框架 web_frame.py from werkzeug.local import LocalStack, LocalProxy def get_request_cont ...

  8. Data URL scheme 笔记

    0x01起因 今天做CTF的时候,发现一堆数据,大概是这样的 data:image/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAAIUAAACFCAYAAAB12js8AAA ...

  9. angular5引入sass

    angular/cli支持使用sass新建工程:如果是新建一个angular工程采用sass:ng new My_New_Project --style=sass这样所有样式的地方都将采用sass样式 ...

  10. 基于MFC的Media Player播放器的控件方法和属性介绍

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. 因为使用第三方多媒体库或是第三方控件(Media Player)辅助播放,我们则必须要了解到Media Player控件的一些属性 和方法 ...