C#实现aop思想有两种方式
一种是MVC框架中带有的过滤器,只要实现控制器的基类就可以使用。配合attribute可以实现验证功能。因为webapi相当于没有页面的MVC,所以也可以使用。
点此跳转
** 另一种是使用attribute配合一些接口实现,该方式比上一种复杂,但更类似于java中spring提供的面向注解思想。只要在要切片的类上附加该attribute就可以使用**
本篇讲第二种方式实现
首先创建一个拦截器注册器,分别实现* ContextAttribute* ,IContributeObjectSink 接口,并继承基类的构造函数。
其中
//以attribute形式定义一个拦截器注册器
[AttributeUsage(AttributeTargets.Class)]
public class CusAttribute : ContextAttribute, IContributeObjectSink
{
public CusAttribute() : base("Cus")
{
}
/// <summary>
/// 用于接收服务器对象的消息接收器
/// </summary>
/// <param name="obj"></param>
/// <param name="nextSink"></param>
/// <returns></returns>
public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink nextSink)
{
//注册一个拦截器,参数是消息池
return new AopMethod(nextSink);
}
}
创建一个空特性,以便拦截的时候识别使用
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class AopAtt : Attribute
{
}
创建拦截器
//消息接收器对象,用于监听消息
public class AopMethod : IMessageSink
{
//本地的消息池对象
public readonly IMessageSink NextSink;
IMessageSink IMessageSink.NextSink => throw new NotImplementedException();
//提供一个有参构造器,供拦截器注册器注入消息池对象
public AopMethod(IMessageSink NextSink)
{
this.NextSink = NextSink;
}
//自定义方法,函数名和函数体随意,后续调用
public void PreProceed(IMessage msg)
{
var message = msg as IMethodMessage;
var paramss = message.Args;
Console.WriteLine(string.Format("方法执行前,入参为:{0}", string.Join(",", paramss.ToArray())));
}
//自定义方法,函数名和函数体随意,后续调用
public void PostProceed(IMessage msg)
{
var message = msg as IMethodMessage;
var paramss = message.Args;
Console.WriteLine(string.Format("方法执行后,返参为:{0}", paramss.ToString()));
}
//用于处理异步消息
public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
{
return null;
}
//用于处理同步消息
public IMessage SyncProcessMessage(IMessage msg)
{
IMessage message = null;
IMethodCallMessage callMessage = msg as IMethodCallMessage;
// 判断方法是否拦截(判断方法有没有上面定义的 AOPMethodAttribute 特性)
if (callMessage != null && (Attribute.GetCustomAttribute(callMessage.MethodBase, typeof(AopAtt))) != null)
{
// 执行前
PreProceed(msg);
// invoke 执行原方法
message = NextSink.SyncProcessMessage(msg);
// 执行后
PostProceed(message);
}
else
{
message = NextSink.SyncProcessMessage(msg);
}
return message;
}
}
最后目标类实现ContextBoundObject接口,在目标类前面附加拦截器注册器attribute,然后在要拦截的方法前用附加拦截器attribute
[Cus]
class Program:ContextBoundObject
{
static void Main(string[] args)
{
Thread.Sleep(1000);
var NewClass = new Program().InitClass();
Console.WriteLine("方法run");
Console.ReadLine();
}
//不能切入静态方法,因为静态方法在编译中和类一样最先编译,先于特性,所以编译静态方法时尚无特性类可以附加
[AopAtt]
public List<Student> InitClass()
{
List<Student> students = new List<Student>();
students.Add(new Student()
{
Name = "Amy",
Id = 1,
Age = 13,
Created = DateTime.Now,
IsDeleted = false,
});
return students;
}
}