使用 Kind.Around 来做一个 Cache 的Attribue

这个是可以用做Cache或者Retry的。下面我们就来做一个Cache的拦截器。

Cache

using AspectInjector.Broker;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    [Aspect(Scope.PerInstance)]
    [Injection(typeof(CacheAttribute))]

    public class CacheAttribute : Attribute
    {
        private Dictionary<string, object> _cache = new Dictionary<string, object>();
        [Advice(Kind.Around)]
        public object Wrap(
            [Argument(Source.Type)] Type type,
            [Argument(Source.Name)] string name,
            [Argument(Source.Target)] Func<object[], object> target,
            [Argument(Source.Arguments)] object[] arg)
        {
            var values = arg.Select(x => x.ToString());

            var key = $"{type.FullName}.{name},{string.Join(",", values)}";
            if (_cache.ContainsKey(key))
            { 
                return _cache[key];
            }
            Console.WriteLine($"start {key}");
            var x = target(arg);
            _cache[key] = x;
            Console.WriteLine("end");
            return x;
        }
    }
}


Source.Type 表示方法所在的类 Source.Name 表示的是原生函数名 taget原方法 arg 调用的方法传进来的参数。

通过type和name arg我们就可以确定它的唯一性了。 如果参数不是简单类型,你可能还需要考虑这样写是不是具有唯一性

调用代码

using Aspects.Cache;
using System;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static async Task Main(string[] args)
        { 
            var result = Calculator.Calculate(600, 300);
            Console.WriteLine(result);

            result = Calculator.Calculate(600, 300);
            Console.WriteLine(result);
        }
    }
}

输出

start ConsoleApp1.Calculator.Calculate,600,300
end
900
900
最近更新的
...