这个是可以用做Cache或者Retry的。下面我们就来做一个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