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

  • 相关阅读:
    USACO 3.3 A Game
    USACO 3.3 Camelot
    USACO 3.3 Shopping Offers
    USACO 3.3 TEXT Eulerian Tour中的Cows on Parade一点理解
    USACO 3.3 Riding the Fences
    USACO 3.2 Magic Squares
    USACO 3.2 Stringsobits
    USACO 3.2 Factorials
    USACO 3.2 Contact
    USACO 3.1 Humble Numbers
  • 原文地址:https://www.cnblogs.com/weihanli/p/12815729.html
Copyright © 2011-2022 走看看