zoukankan      html  css  js  c++  java
  • FluentAspects -- 基于 Fluent API 的 Aop

    FluentAspects -- 基于 Fluent API 的 Aop

    Intro

    上次我们做了一个简单的 AOP 实现示例,但是实现起来主要是基于 Attribute 来做的,对于代码的侵入性太强,于是尝试实现基于 Fluent API 的方式来做 AOP 。

    抽象 InterceptorResolver

    原来获取方法执行的 Interceptor 是通过 Attribute 来获取的,现在我们只需要将获取 Interceptor 的逻辑抽象出来就可以实现不必依赖于 Attribute

    方法执行上下文定义:

    public interface IInvocation
    {
        public MethodInfo ProxyMethod { get; }
    
        public object ProxyTarget { get; }
    
        public MethodInfo Method { get; }
    
        public object Target { get; }
    
        public object[] Arguments { get; }
    
        Type[] GenericArguments { get; }
    
        public object ReturnValue { get; set; }
    }
    
    

    方法拦截器 Interceptor 接口定义:

    public interface IInterceptor
    {
        Task Invoke(IInvocation invocation, Func<Task> next);
    }
    

    自定义 Interceptor 只需要继承这个接口实现相应的逻辑就好了

    获取 IInterceptorResolver 接口定义:

    public interface IInterceptorResolver
    {
        IReadOnlyCollection<IInterceptor> ResolveInterceptors(IInvocation invocation);
    }
    

    原来基于 Attribute 获取 Interceptor 的方式可以实现一个 AttributeInterceptorResolver

    想要基于 Fluent API 来获取 Interceptor ,只需要实现基于 Fluent API 的 InterceptorResolver 就可以了,具体的实现可以参考 FluentConfigInterceptorResolver

    示例预览

    测试服务定义:

    public interface ISvc1
    {
        void Invoke();
    }
    
    public interface ISvc2
    {
        void Invoke();
    }
    
    public class Svc2 : ISvc2
    {
        public void Invoke()
        {
            Console.WriteLine($"invoking in {GetType().Name} ...");
        }
    
        public void Invoke2()
        {
            Console.WriteLine($"invoking in {GetType().Name} ...");
        }
    }
    
    public class Svc3
    {
        public virtual void Invoke()
        {
            Console.WriteLine($"invoking in {GetType().Name} ...");
        }
    }
    
    public class Svc4
    {
        public virtual void Invoke()
        {
            Console.WriteLine($"invoking in {GetType().Name} ...");
        }
    
        public void Invoke2()
        {
            Console.WriteLine($"invoking2 in {GetType().Name} ...");
        }
    
        public virtual void Invoke3()
        {
            Console.WriteLine($"invoking3 in {GetType().Name} ...");
        }
    }
    

    测试 Interceptor

    internal class LogInterceptor : IInterceptor
    {
        public async Task Invoke(IInvocation invocation, Func<Task> next)
        {
            Console.WriteLine($"invoke {invocation.ProxyMethod} in {GetType().Name} begin");
            await next();
            Console.WriteLine($"invoke {invocation.ProxyMethod} in {GetType().Name} end");
        }
    }
    

    测试代码:

    public static void Main(string[] args)
    {
        var services = new ServiceCollection();
        services.AddFluentAspects(options =>
        {
            // 为所有拦截的方法添加拦截器
            options.InterceptAll()
                .With<LogInterceptor>()
                ;
            // 对 Svc3 类型禁用拦截器
            options.NoInterceptType<Svc3>();
            // Svc4 类型的 Invoke3() 方法禁用拦截器
            options.NoInterceptMethod<Svc4>(s => s.Invoke3());
        });
        services.AddTransientProxy<Svc4>();
        var serviceProvider = services.BuildServiceProvider();
        var proxyFactory = serviceProvider.GetRequiredService<IProxyFactory>();
    
        var svc1 = proxyFactory.CreateProxy<ISvc1>();
        svc1.Invoke();
        Console.WriteLine();
    
        var svc2 = proxyFactory.CreateProxy<ISvc2, Svc2>();
        svc2.Invoke();
        Console.WriteLine();
    
        var svc3 = proxyFactory.CreateProxy<Svc3>();
        svc3.Invoke();
        Console.WriteLine();
    
        var svc4 = proxyFactory.CreateProxyWithTarget<ISvc2, Svc2>(new Svc2());
        svc4.Invoke();
        Console.WriteLine();
    
        // 直接从注册的服务中获取
        var svc5 = serviceProvider.GetRequiredService<Svc4>();
        svc5.Invoke();
        Console.WriteLine();
        svc5.Invoke2();
        Console.WriteLine();
        svc5.Invoke3();
        Console.WriteLine();
    
        Console.WriteLine("finished");
        Console.ReadLine();
    }
    

    输出结果预览:

    More

    最近十几天的时间一直在搞这个,相比之前写的示例,真正实现一个完整的 AOP 框架还是要做比较多的事情的,之前的 AOP 示例,没有考虑泛型,也没有什么设计,所以前面的示例只能算是一个小玩具。

    在实现的过程中,参考了很多 AspectCore 的代码,有一些代码甚至是直接从 AspectCore 里抄过来的。

    推荐大家有机会研究学习一下柠檬大佬的 AspectCore 的源码,这个 AOP 框架的代码组织,代码细节都挺不错的。

    AspectCore 源码地址: https://github.com/dotnetcore/AspectCore-Framework

    Reference

  • 相关阅读:
    水晶报表显示到aspx页面中
    Python 2.7获取网站源代码的几种方式_20160924
    Seal Report_20160923
    MySQL交叉表处理_20160923
    MySQL日期处理函数_20160922
    MySQL文本处理函数2_20160921
    kettle及数据库导数_20160920
    MySQL常用的数据类型及函数_20160920
    MySQL记录_20160919
    [vuex]
  • 原文地址:https://www.cnblogs.com/weihanli/p/12815729.html
Copyright © 2011-2022 走看看