Exemplo n.º 1
0
 public abstract Task Invoke(AspectDelegate next);
Exemplo n.º 2
0
 /// <summary>
 /// 拦截器
 /// </summary>
 /// <param name="aspectContext">拦截上下文</param>
 /// <param name="_next">下一个拦截器 最后一个是执行被拦截的方法</param>
 /// <returns></returns>
 public abstract Task OnInvocation(AspectContext aspectContext, AspectDelegate _next);
        public async override Task Invoke(AspectContext context, AspectDelegate next)
        {
            CacheAbleAttribute attribute = context.GetAttribute <CacheAbleAttribute>();

            if (attribute == null)
            {
                await context.Invoke(next);

                return;
            }

            try
            {
                Database = RedisClient.GetDatabase();

                string cacheKey = KeyGenerator.GetCacheKey(context.ServiceMethod, context.Parameters, attribute.CacheKeyPrefix);

                string cacheValue = await GetCacheAsync(cacheKey);

                Type returnType = context.GetReturnType();

                if (string.IsNullOrWhiteSpace(cacheValue))
                {
                    if (attribute.OnceUpdate)
                    {
                        string     lockKey = $"Lock_{cacheKey}";
                        RedisValue token   = Environment.MachineName;

                        if (await Database.LockTakeAsync(lockKey, token, TimeSpan.FromSeconds(10)))
                        {
                            try
                            {
                                var result = await RunAndGetReturn(context, next);
                                await SetCache(cacheKey, result, attribute.Expiration);

                                return;
                            }
                            finally
                            {
                                await Database.LockReleaseAsync(lockKey, token);
                            }
                        }
                        else
                        {
                            for (int i = 0; i < 5; i++)
                            {
                                Thread.Sleep(i * 100 + 500);
                                cacheValue = await GetCacheAsync(cacheKey);

                                if (!string.IsNullOrWhiteSpace(cacheValue))
                                {
                                    break;
                                }
                            }
                            if (string.IsNullOrWhiteSpace(cacheValue))
                            {
                                var defaultValue = CreateDefaultResult(returnType);
                                context.ReturnValue = ResultFactory(defaultValue, returnType, context.IsAsync());
                                return;
                            }
                        }
                    }
                    else
                    {
                        var result = await RunAndGetReturn(context, next);
                        await SetCache(cacheKey, result, attribute.Expiration);

                        return;
                    }
                }
                var objValue = await DeserializeCache(cacheKey, cacheValue, returnType);

                //缓存值不可用
                if (objValue == null)
                {
                    await context.Invoke(next);

                    return;
                }

                context.ReturnValue = ResultFactory(objValue, returnType, context.IsAsync());
            }
            catch (Exception)
            {
                if (context.ReturnValue == null)
                {
                    await context.Invoke(next);
                }
            }
        }
 public override Task Invoke(AspectContext context, AspectDelegate next)
 {
     context.Parameters[0] = FakeProperty?.Val;
     return(context.Invoke(next));
 }
Exemplo n.º 5
0
 public abstract Task Handle(AspectContext context, AspectDelegate next);
Exemplo n.º 6
0
        public async override Task Invoke(AspectContext context, AspectDelegate next)
        {
            var returnType = context.GetReturnParameter().Type;
            var hasCache   = context.ImplementationMethod.GetCustomAttributes(typeof(CacheAttribute), false).Any();

            if (returnType == typeof(void) ||
                returnType == typeof(Task) ||
                returnType == typeof(ValueTask) ||
                !hasCache)
            {
                await next(context);

                return;
            }

            if (context.IsAsync())
            {
                returnType = returnType.GenericTypeArguments.FirstOrDefault();
            }

            var cacheKey = this.CreateCacheKey(context);

            this.Log("trying to get", cacheKey);

            var cacheService = (ICacheService)context.ServiceProvider.GetService(typeof(ICacheService));

            var cachedResult = cacheService.Get(cacheKey);

            if (cachedResult == null)
            {
                this.Log("key not found", cacheKey);
                await next(context);

                var returnValue = context.IsAsync()
                    ? await context.UnwrapAsyncReturnValue()
                    : context.ReturnValue;

                this.Log("trying to set", cacheKey);
                if (!cacheService.Set(cacheKey, returnValue))
                {
                    this.Log("failed to set", cacheKey);
                }
            }
            else
            {
                this.Log("found key", cacheKey);
                if (context.IsAsync())
                {
                    if (context.ImplementationMethod.ReturnType == typeof(Task <>).MakeGenericType(returnType))
                    {
                        context.ReturnValue = typeof(Task)
                                              .GetMethod(nameof(Task.FromResult))
                                              .MakeGenericMethod(returnType)
                                              .Invoke(null, new[] { cachedResult });
                    }
                    if (context.ImplementationMethod.ReturnType == typeof(ValueTask <>).MakeGenericType(returnType))
                    {
                        context.ReturnValue = Activator
                                              .CreateInstance(typeof(ValueTask <>).MakeGenericType(returnType), cachedResult);
                    }
                }
                else
                {
                    context.ReturnValue = cachedResult;
                }
            }
        }
 public Task Invoke(AspectContext context, AspectDelegate next)
 {
     return(_aspectDelegate(next)(context));
 }
Exemplo n.º 8
0
 public override Task Invoke(AspectContext context, AspectDelegate next)
 {
     context.Parameters[0] = "lemon";
     return(context.Invoke(next));
 }
Exemplo n.º 9
0
        public override async Task Invoke(AspectContext context, AspectDelegate next)
        {
            //一个HystrixCommand中保持一个policy对象即可
            //其实主要是CircuitBreaker要求对于同一段代码要共享一个policy对象
            //根据反射原理,同一个方法的MethodInfo是同一个对象,但是对象上取出来的HystrixCommandAttribute
            //每次获取的都是不同的对象,因此以MethodInfo为Key保存到policies中,确保一个方法对应一个policy实例
            policies.TryGetValue(context.ServiceMethod, out AsyncPolicy policy);
            lock (policies)            //因为Invoke可能是并发调用,因此要确保policies赋值的线程安全
            {
                if (policy == null)
                {
                    policy = Policy.NoOpAsync();                    //创建一个空的Policy
                    if (IsEnableCircuitBreaker)
                    {
                        policy = policy.WrapAsync(Policy.Handle <Exception>().CircuitBreakerAsync(IsForceDowngrade ? 1 : ExceptionsAllowedBeforeBreaking, TimeSpan.FromMilliseconds(MillisecondsOfBreak)));
                    }
                    if (TimeOutMilliseconds > 0)
                    {
                        policy = policy.WrapAsync(Policy.TimeoutAsync(() => TimeSpan.FromMilliseconds(TimeOutMilliseconds), TimeoutStrategy.Pessimistic));
                    }
                    if (MaxRetryTimes > 0)
                    {
                        policy = policy.WrapAsync(Policy.Handle <Exception>().WaitAndRetryAsync(MaxRetryTimes, i => TimeSpan.FromMilliseconds(RetryIntervalMilliseconds)));
                    }

                    AsyncPolicy policyFallBack = Policy
                                                 .Handle <Exception>()
                                                 .FallbackAsync(async(ctx, t) =>
                    {
                        var fallBackMethod    = context.ServiceMethod.DeclaringType.GetMethod(this.FallBackMethod);
                        Object fallBackResult = fallBackMethod.Invoke(context.Implementation, context.Parameters);
                        //不能如下这样,因为这是闭包相关,如果这样写第二次调用Invoke的时候context指向的
                        //还是第一次的对象,所以要通过Polly的上下文来传递AspectContext
                        //context.ReturnValue = fallBackResult;
                        AspectContext aspectContext = (AspectContext)ctx["aspectContext"];
                        aspectContext.ReturnValue   = fallBackResult;
                    }, async(ex, t) =>
                    {
                        t.Add("error", ex.Message);
                    });

                    policy = policyFallBack.WrapAsync(policy);
                    //放入
                    policies.TryAdd(context.ServiceMethod, policy);
                }
            }

            //把本地调用的AspectContext传递给Polly,主要给FallbackAsync中使用,避免闭包的坑
            Context pollyCtx = new Context();

            pollyCtx["aspectContext"] = context;

            // 强制降级
            if (IsForceDowngrade)
            {
                await policy.ExecuteAsync((i) => throw new Core.AngleExceptions("force downgrade"), pollyCtx);

                return;
            }

            //Install-Package Microsoft.Extensions.Caching.Memory
            if (CacheTTLMilliseconds > 0)
            {
                //用类名+方法名+参数的下划线连接起来作为缓存key
                string cacheKey = "HystrixMethodCacheManager_Key_" + context.ServiceMethod.DeclaringType
                                  + "." + context.ServiceMethod + string.Join("_", context.Parameters);
                //尝试去缓存中获取。如果找到了,则直接用缓存中的值做返回值
                if (memoryCache.TryGetValue(cacheKey, out var cacheValue))
                {
                    context.ReturnValue = cacheValue;
                }
                else
                {
                    //如果缓存中没有,则执行实际被拦截的方法
                    await policy.ExecuteAsync(ctx => next(context), pollyCtx);

                    //存入缓存中
                    using (var cacheEntry = memoryCache.CreateEntry(cacheKey))
                    {
                        cacheEntry.Value = context.ReturnValue;
                        cacheEntry.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMilliseconds(CacheTTLMilliseconds);
                    }
                }
            }
            else            //如果没有启用缓存,就直接执行业务方法
            {
                await policy.ExecuteAsync(ctx => next(context), pollyCtx);
            }
        }
Exemplo n.º 10
0
        public override async Task Invoke(AspectContext context, AspectDelegate next)
        {
            int methodtoken = context.ServiceMethod.MetadataToken; //System.Reflection.MethodBase.GetCurrentMethod().MetadataToken;

            this.SetGlobalConfig();
            //查询字典中是否保存过当前函数的policy
            Share.GlobalStatic.dict_policies.TryGetValue(methodtoken, out AsyncPolicy policy);

            if (policy == null)
            {
                policy = this.SetFallBackPolicy(policy, context);

                AsyncPolicy wrappolicy = null;
                wrappolicy = this.SetCircuitBreaker(wrappolicy);
                wrappolicy = this.SetRetry(wrappolicy);
                wrappolicy = this.SetTimeout(wrappolicy);

                //如果降级启用,就把降级策略和以上策略进行组合,注意组合顺序,顺序不对可能部分策略失效(不确定)
                if (IsEnableFallBack == E_Hystrix.Enable)
                {
                    policy = policy.WrapAsync(wrappolicy);
                }
                else
                {
                    policy = wrappolicy;
                }

                //添加的时候,锁住再查询一次看字典中是否存在key,如果存在,说明并发的时候加入过这个,就不需要再加入了
                lock (lock_Hystrix)
                {
                    if (!Share.GlobalStatic.dict_policies.ContainsKey(methodtoken))
                    {
                        Share.GlobalStatic.dict_policies.TryAdd(methodtoken, policy);
                    }
                }
            }
            //policy.ExecuteAsync执行的时候,把pollyCtx当参数传递过去,避免闭包问题
            Context pollyCtx = new Context();

            pollyCtx["aspectContext"] = context;

            //todo:增加缓存算法,不然内存很快爆满,OneNote里有
            //全局启用,局部启用,缓存才启用
            if (cache != null && cache.Enable && IsEnableCache == E_Hystrix.Enable)
            {
                string cacheKey = MD5Helper.MD5Encrypt32("CM_Hystrix_" + context.ServiceMethod.DeclaringType + "." + context.ServiceMethod + string.Join("_", context.Parameters));
                //尝试去缓存中获取。如果找到了,则直接用缓存中的值做返回值
                if (cache.TryGetValue(cacheKey, out var cacheValue))
                {
                    context.ReturnValue = cacheValue;
                }
                else
                {
                    //如果缓存中没有,则执行实际被拦截的方法
                    await policy.ExecuteAsync(ctx => next(context), pollyCtx);

                    //把返回值存入缓存中
                    cache.Add(cacheKey, context.ReturnValue, CacheTTLSeconds == 0 ? cache.Expiration : CacheTTLSeconds);
                }
            }
            else//如果没有启用缓存,就直接执行业务方法
            {
                if (policy == null)
                {
                    await next(context);//直接执行
                }
                else
                {
                    await policy.ExecuteAsync(ctx => next(context), pollyCtx);//polly执行
                }
            }
        }
Exemplo n.º 11
0
        public override Task Invoke(AspectContext context, AspectDelegate next)
        {
            var scopedService = context.ServiceProvider.GetService(typeof(ScopedService));

            return(context.Invoke(next));
        }
Exemplo n.º 12
0
        public override async Task Invoke(AspectContext context, AspectDelegate next)
        {
            //await next(context);

            //一个HystrixCommand中保持一个policy对象即可
            //其实主要是CircuitBreaker要求对于同一段代码要共享一个policy对象
            //根据反射原理,同一个方法的MethodInfo是同一个对象,但是对象上取出来的HystrixCommandAttribute
            //每次获取的都是不同的对象,因此以MethodInfo为Key保存到policies中,确保一个方法对应一个policy实例
            //policies.TryGetValue(context.ServiceMethod, out Policy policy);
            lock (this)//因为Invoke可能是并发调用,因此要确保policies赋值的线程安全
            {
                if (policy == null)
                {
                    policy = Policy
                             .Handle <ArgumentException>()
                             .FallbackAsync(async(ctx, t) =>
                    {
                        AspectContext aspectContext = (AspectContext)ctx["aspectContext"];
                        var fallBackMethod          = context.ServiceMethod.DeclaringType.GetMethod(this.FallBackMethod);
                        Object fallBackResult       = fallBackMethod.Invoke(context.Implementation, context.Parameters);

                        //不能如下这样,因为这是闭包相关,如果这样写第二次调用Invoke的时候context指向的
                        //还是第一次的对象,所以要通过Polly的上下文来传递AspectContext
                        //context.ReturnValue = fallBackResult;
                        aspectContext.ReturnValue = fallBackResult;

                        Console.WriteLine("我也是醉了");
                    }, async(ex, t) =>
                    {
                        //Console.WriteLine("哈哈 我终于进来了");
                        //context.ReturnValue = "哈哈哈";

                        Console.WriteLine("我TM也是醉了");
                    });
                    // 设置 最大重试次数限制
                    if (MaxRetryTimes > 0)
                    {
                        policy = policy.WrapAsync(Policy.Handle <ArgumentException>()
                                                  .WaitAndRetryAsync(MaxRetryTimes,
                                                                     i => TimeSpan.FromMilliseconds(RetryIntervalMilliseconds)));
                    }

                    // 启用熔断保护(CircuitBreaker)
                    if (IsEnableCircuitBreaker)
                    {
                        policy = policy.WrapAsync(Policy.Handle <ArgumentException>()
                                                  .CircuitBreakerAsync(ExceptionsAllowedBeforeBreaking,
                                                                       TimeSpan.FromMilliseconds(MillisecondsOfBreak), (ex, ts) =>
                        {
                            // assuem to do logging
                            Console.WriteLine($"Service API OnBreak -- ts = {ts.Seconds}s, ex.message = {ex.Message}");
                        }, () =>
                        {
                            // assume to do logging
                            Console.WriteLine($"Service API OnReset");
                        }));
                    }

                    // 设置超时时间
                    if (TimeOutMilliseconds > 0)
                    {
                        policy = policy.WrapAsync(Policy.TimeoutAsync(() =>
                                                                      TimeSpan.FromMilliseconds(TimeOutMilliseconds),
                                                                      Polly.Timeout.TimeoutStrategy.Pessimistic));
                    }
                    //policy = policyFallBack.WrapAsync(policy);
                    //放入
                    //policies.TryAdd(context.ServiceMethod, policy);
                }
                ;
            }

            //把本地调用的AspectContext传递给Polly,主要给FallbackAsync中使用,避免闭包的坑
            Context pollyCtx = new Context();

            pollyCtx["aspectContext"] = context;

            //Install-Package Microsoft.Extensions.Caching.Memory
            if (CacheTTLMilliseconds > 0)
            {
                //用类名+方法名+参数的下划线连接起来作为缓存key
                var cacheKey = CustomCacheKey(context);
                //尝试去缓存中获取。如果找到了,则直接用缓存中的值做返回值
                if (_memoryCache.TryGetValue(cacheKey, out var cacheValue))
                {
                    context.ReturnValue = cacheValue;
                }
                else
                {
                    //如果缓存中没有,则执行实际被拦截的方法
                    await policy.ExecuteAsync(ctx => next(context), pollyCtx);

                    //存入缓存中
                    using (var cacheEntry = _memoryCache.CreateEntry(cacheKey))
                    {
                        cacheEntry.Value = context.ReturnValue;
                        cacheEntry.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMilliseconds(CacheTTLMilliseconds);
                    }
                }
            }
            else//如果没有启用缓存,就直接执行业务方法
            {
                await policy.ExecuteAsync(ctx => next(context), pollyCtx);
            }
        }
 public override Task Invoke(AspectDelegate next)
 {
     return(next(this));
 }
Exemplo n.º 14
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="context"></param>
 /// <param name="next"></param>
 /// <returns></returns>
 public async override Task Invoke(AspectContext context, AspectDelegate next)
 {
     var interceptor = context.ServiceProvider.GetService <AuthorizationInterceptor>();
     await interceptor.Invoke(context, next);
 }
Exemplo n.º 15
0
 public override void Invoke(AspectContext context, AspectDelegate next)
 {
     syncCache.GetOrAdd(context.Method, CreateInvoke)(context, next);
 }
Exemplo n.º 16
0
        //public override void OnExit(MethodExecutionArgs args)
        //{
        //    var type = (string)args.Arguments[0];
        //    var code = (string)args.ReturnValue;
        //    Logger.PrintHeader(type);
        //    Logger.PrintLn(code);

        //    base.OnExit(args);
        //}

        public override Task Invoke(AspectContext context, AspectDelegate next)
        {
            throw new System.NotImplementedException();
        }
Exemplo n.º 17
0
        public override Task Invoke(AspectContext context, AspectDelegate next)
        {
            ISyncPolicy policy = Policy
                                 .Handle <Exception>()
                                 .Fallback(() =>
            {
                var fallBackMethod    = context.ServiceMethod.DeclaringType.GetMethod(this.FallBackMethod);
                Object fallBackResult = fallBackMethod.Invoke(context.Implementation, context.Parameters);
                context.ReturnValue   = fallBackResult;
            });

            if (MaxRetryTimes > 0)
            {
                policy = policy.Wrap(Policy.Handle <Exception>().WaitAndRetry(MaxRetryTimes, i => TimeSpan.FromMilliseconds(RetryIntervalMilliseconds)));
            }
            if (EnableCircuitBreaker)
            {
                policy = policy.Wrap(Policy.Handle <Exception>().CircuitBreaker(ExceptionsAllowedBeforeBreaking, TimeSpan.FromMilliseconds(RetryIntervalMilliseconds)));
            }
            if (TimeOutMilliseconds > 0)
            {
                policy = policy.Wrap(Policy.Timeout(() => TimeSpan.FromMilliseconds(TimeOutMilliseconds), TimeoutStrategy.Pessimistic));
            }
            //Install-Package Microsoft.Extensions.Caching.Memory
            if (CacheTTLMilliseconds > 0)
            {
                //用类名+方法名+参数的下划线连接起来作为缓存key
                string cacheKey = "HystrixMethodCacheManager_Key_" + context.ServiceMethod.DeclaringType
                                  + "." + context.ServiceMethod + string.Join("_", context.Parameters);
                Object cacheValue;
                //尝试去缓存中获取
                if (memoryCache.TryGetValue(cacheKey, out cacheValue))
                {
                    context.ReturnValue = cacheValue;
                    return(Task.FromResult(0));
                }
                else
                {
                    object returnValue = null;
                    policy.Execute(() =>
                    {
                        //执行实际的方法
                        returnValue = context.Invoke(next);
                    });
                    using (var cacheEntry = memoryCache.CreateEntry(cacheKey))
                    {
                        cacheEntry.Value = context.ReturnValue;
                        cacheEntry.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMilliseconds(CacheTTLMilliseconds);
                    }
                    return(Task.FromResult(returnValue));
                }
            }
            else//如果没有启用缓存,就直接执行业务方法
            {
                object returnValue = null;
                policy.Execute(() =>
                {
                    returnValue = context.Invoke(next);
                });
                return(Task.FromResult(returnValue));
            }
        }
Exemplo n.º 18
0
        public override async Task Invoke(AspectContext context, AspectDelegate next)
        {
            //熔断一般都是针对方法的
            //一个HystrixCommand中保持一个policy对象即可
            //其实主要是CircuitBreaker要求对于同一段代码要共享一个policy对象
            //根据反射原理,同一个方法就对应一个HystrixCommandAttribute,无论几次调用,
            //而不同方法对应不同的HystrixCommandAttribute对象,天然的一个policy对象共享
            //因为同一个方法共享一个policy,因此这个CircuitBreaker是针对所有请求的。
            //Attribute也不会在运行时再去改变属性的值,共享同一个policy对象也没问题
            lock (this)//因为Invoke可能是并发调用,因此要确保policy赋值的线程安全
            {
                if (policy == null)
                {
                    policy = Policy.NoOpAsync();//创建一个空的Policy
                    if (EnableCircuitBreaker)
                    {
                        policy = policy.WrapAsync(Policy.Handle <Exception>().CircuitBreakerAsync(ExceptionsAllowedBeforeBreaking, TimeSpan.FromMilliseconds(MillisecondsOfBreak)));
                    }
                    if (TimeOutMilliseconds > 0)
                    {
                        policy = policy.WrapAsync(Policy.TimeoutAsync(() => TimeSpan.FromMilliseconds(TimeOutMilliseconds), Polly.Timeout.TimeoutStrategy.Pessimistic));
                    }
                    if (MaxRetryTimes > 0)
                    {
                        policy = policy.WrapAsync(Policy.Handle <Exception>().WaitAndRetryAsync(MaxRetryTimes, i => TimeSpan.FromMilliseconds(RetryIntervalMilliseconds)));
                    }
                    Policy policyFallBack = Policy
                                            .Handle <Exception>()
                                            .FallbackAsync(async(ctx, t) =>
                    {
                        AspectContext aspectContext = (AspectContext)ctx["aspectContext"];
                        var fallBackMethod          = context.ServiceMethod.DeclaringType.GetMethod(this.FallBackMethod);
                        Object fallBackResult       = fallBackMethod.Invoke(context.Implementation, context.Parameters);
                        //不能如下这样,因为这是闭包相关,如果这样写第二次调用Invoke的时候context指向的
                        //还是第一次的对象,所以要通过Polly的上下文来传递AspectContext
                        //context.ReturnValue = fallBackResult;
                        aspectContext.ReturnValue = fallBackResult;
                    }, async(ex, t) => { });

                    policy = policyFallBack.WrapAsync(policy);
                }
            }

            //把本地调用的AspectContext传递给Polly,主要给FallbackAsync中使用,避免闭包的坑
            Context pollyCtx = new Context();

            pollyCtx["aspectContext"] = context;

            //Install-Package Microsoft.Extensions.Caching.Memory
            if (CacheTTLMilliseconds > 0)
            {
                //用类名+方法名+参数的下划线连接起来作为缓存key
                string cacheKey = "HystrixMethodCacheManager_Key_" + context.ServiceMethod.DeclaringType
                                  + "." + context.ServiceMethod + string.Join("_", context.Parameters);
                //尝试去缓存中获取。如果找到了,则直接用缓存中的值做返回值
                if (memoryCache.TryGetValue(cacheKey, out var cacheValue))
                {
                    context.ReturnValue = cacheValue;
                }
                else
                {
                    //如果缓存中没有,则执行实际被拦截的方法
                    await policy.ExecuteAsync(ctx => next(context), pollyCtx);

                    //存入缓存中
                    using (var cacheEntry = memoryCache.CreateEntry(cacheKey))
                    {
                        cacheEntry.Value = context.ReturnValue;
                        cacheEntry.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMilliseconds(CacheTTLMilliseconds);
                    }
                }
            }
            else//如果没有启用缓存,就直接执行业务方法
            {
                await policy.ExecuteAsync(ctx => next(context), pollyCtx);
            }
        }
Exemplo n.º 19
0
 public override Task Invoke(AspectContext context, AspectDelegate next)
 {
     Console.WriteLine("call interceptor");
     return(context.Invoke(next));
 }
Exemplo n.º 20
0
 public override async Task Invoke(AspectContext context, AspectDelegate next)
 {
     Console.WriteLine("global");
     await next(context);
 }
Exemplo n.º 21
0
 public async override Task Invoke(AspectContext context, AspectDelegate next)
 {
     await next(context);
 }
Exemplo n.º 22
0
 public override Task Invoke(AspectContext context, AspectDelegate next)
 {
     return(context.Invoke(next));
 }
        public async override Task Invoke(AspectContext context, AspectDelegate next)
        {
            if (!IsOpen)
            {
                await next(context);

                return;
            }

            try
            {
                var redis  = context.ServiceProvider.GetService <IRedisService>();
                var option = context.ServiceProvider.GetService <IOptions <CacheOptions> >();

                Type returnType = context.GetReturnType();

                string key = Utils.GetParamterKey("", "", Key, context.Parameters);

                var result = redis.HashGet <string>(HashKey, key, option.Value.RedisRead, RedisSerializerOptions.RedisValue);

                if (result.IsEmpty())
                {
                    await next(context);

                    var value = await context.GetReturnValue();

                    if (value != null)
                    {
                        var json = JsonConvert.SerializeObject(value);

                        if (Seconds > 0)
                        {
                            bool exists = redis.KeyExists(HashKey, option.Value.RedisRead);

                            redis.HashSet(HashKey, key, json, option.Value.RedisWrite, RedisSerializerOptions.RedisValue);

                            if (!exists)
                            {
                                redis.KeyExpire(HashKey, Seconds, option.Value.RedisWrite);
                            }
                        }
                        else
                        {
                            redis.HashSet(HashKey, key, json, option.Value.RedisWrite, RedisSerializerOptions.RedisValue);
                        }
                    }
                }
                else
                {
                    var value = JsonConvert.DeserializeObject(result, returnType);

                    context.ReturnValue = context.ResultFactory(value, returnType, context.IsAsync());
                }
            }
            catch (Exception ex)
            {
                var logger = context.ServiceProvider.GetService <ILogger <RedisCacheMethodAttribute> >();

                logger.LogError($"RedisCacheMethod:Key:{Key} {ex.FormatMessage()}");

                await next(context);
            }
        }
Exemplo n.º 24
0
 public override Task Invoke(AspectContext context, AspectDelegate next)
 {
     context.Parameters[0] = context.Parameters[0].ToString().ToUpper();
     return(next(context));
 }
Exemplo n.º 25
0
 public override async Task Invoke(AspectContext context, AspectDelegate next)
 {
     InvokeBefore(context);
     await context.Invoke(next);
 }
 public override async Task Invoke(AspectContext context, AspectDelegate next)
 {
     await ProcessGetOrCreateAsync(context, next);
 }
Exemplo n.º 27
0
 public override async Task Handle(AspectContext context, AspectDelegate next)
 {
     await next(context);
 }
Exemplo n.º 28
0
 public abstract Task Invoke(AspectContext context, AspectDelegate next);
Exemplo n.º 29
0
        /// <summary>
        /// 执行
        /// </summary>
        public override async Task Invoke(AspectContext context, AspectDelegate next)
        {
            List <string> appendKeyArray = null;

            if (string.IsNullOrWhiteSpace(Key))
            {
                Key =
                    $"{context.ServiceMethod.DeclaringType}.{context.ImplementationMethod.Name}:{context.ServiceMethod.ToString()}";
            }
            else
            {
                if (!AppendKeyParameters.TryGetValue(context.ImplementationMethod, out appendKeyArray))
                {
                    if (Key.IndexOf("{", StringComparison.Ordinal) > -1)
                    {
                        appendKeyArray = new List <string>();
                        var matchs = Regex.Matches(Key, @"\{\w*\:?\w*\}", RegexOptions.None);
                        foreach (Match match in matchs)
                        {
                            if (match.Success)
                            {
                                appendKeyArray.Add(match.Value.TrimStart('{').TrimEnd('}'));
                            }
                        }
                    }

                    AppendKeyParameters.TryAdd(context.ImplementationMethod, appendKeyArray);
                }
            }

            var currentCacheKey = Key;

            if (appendKeyArray != null && appendKeyArray.Count > 0)
            {
                // 获取方法的参数
                var pars = context.ProxyMethod.GetParameters();

                // 设置参数名和值,加入字典
                var dicValue = new Dictionary <string, object>();
                for (var i = 0; i < pars.Length; i++)
                {
                    dicValue.Add(pars[i].Name, context.Parameters[i]);
                }

                foreach (var key in appendKeyArray)
                {
                    if (key.Contains(":"))
                    {
                        var arr       = key.Split(':');
                        var keyFirst  = arr[0];
                        var keySecond = arr[1];

                        if (!dicValue.TryGetValue(keyFirst, out var value))
                        {
                            throw new Warning(
                                      $"Cache {context.ServiceMethod.DeclaringType}.{context.ImplementationMethod.Name} 不包含参数 {keyFirst}");
                        }

                        var ob = Internal.Helper.ToDictionary(value);
                        if (!ob.TryGetValue(keySecond, out object tokenValue))
                        {
                            throw new Warning(
                                      $"Cache {context.ServiceMethod.DeclaringType}.{context.ImplementationMethod.Name} {keyFirst} 不包含参数 {keySecond}");
                        }

                        currentCacheKey = currentCacheKey.Replace("{" + key + "}", tokenValue.ToString());
                    }
                    else
                    {
                        if (!dicValue.TryGetValue(key, out var value))
                        {
                            throw new Warning(
                                      $"Cache {context.ServiceMethod.DeclaringType}.{context.ImplementationMethod.Name} 不包含参数 {key}");
                        }

                        currentCacheKey = currentCacheKey.Replace("{" + key + "}", value.ToString());
                    }
                }
            }

            // 返回值类型
            var returnType = context.IsAsync()
                ? context.ServiceMethod.ReturnType.GetGenericArguments().First()
                : context.ServiceMethod.ReturnType;

            // 从缓存取值
            var cacheValue = await Cache.GetAsync(currentCacheKey, returnType);

            if (cacheValue != null)
            {
                context.ReturnValue = context.IsAsync()
                    ? TaskResultMethod.MakeGenericMethod(returnType).Invoke(null, new object[] { cacheValue })
                    : cacheValue;
                return;
            }

            using (await _lock.LockAsync())
            {
                cacheValue = await Cache.GetAsync(currentCacheKey, returnType);

                if (cacheValue != null)
                {
                    context.ReturnValue = context.IsAsync()
                        ? TaskResultMethod.MakeGenericMethod(returnType).Invoke(null, new object[] { cacheValue })
                        : cacheValue;
                }
                else
                {
                    await next(context);

                    dynamic returnValue =
                        context.IsAsync() ? await context.UnwrapAsyncReturnValue() : context.ReturnValue;

                    Cache.TryAdd(currentCacheKey, returnValue, Expiration);
                }
            }
        }
Exemplo n.º 30
0
        /// <summary>
        /// Proceeds the able async.
        /// </summary>
        /// <returns>The able async.</returns>
        /// <param name="context">Context.</param>
        /// <param name="next">Next.</param>
        private async Task ProceedAbleAsync(AspectContext context, AspectDelegate next)
        {
            if (GetMethodAttributes(context.ServiceMethod).FirstOrDefault(x => x.GetType() == typeof(EasyCachingAbleAttribute)) is EasyCachingAbleAttribute attribute)
            {
                var returnType = context.IsAsync()
                        ? context.ServiceMethod.ReturnType.GetGenericArguments().First()
                        : context.ServiceMethod.ReturnType;

                var cacheKey = KeyGenerator.GetCacheKey(context.ServiceMethod, context.Parameters, attribute.CacheKeyPrefix);

                object cacheValue  = null;
                var    isAvailable = true;
                try
                {
                    cacheValue = await _cacheProvider.GetAsync(cacheKey, returnType);
                }
                catch (Exception ex)
                {
                    if (!attribute.IsHightAvailability)
                    {
                        throw;
                    }
                    else
                    {
                        isAvailable = false;
                        Logger?.LogError(new EventId(), ex, $"Cache provider \"{_cacheProvider.Name}\" get error.");
                    }
                }

                if (cacheValue != null)
                {
                    if (context.IsAsync())
                    {
                        //#1
                        //dynamic member = context.ServiceMethod.ReturnType.GetMember("Result")[0];
                        //dynamic temp = System.Convert.ChangeType(cacheValue.Value, member.PropertyType);
                        //context.ReturnValue = System.Convert.ChangeType(Task.FromResult(temp), context.ServiceMethod.ReturnType);

                        //#2
                        context.ReturnValue =
                            TypeofTaskResultMethod.GetOrAdd(returnType, t => typeof(Task).GetMethods().First(p => p.Name == "FromResult" && p.ContainsGenericParameters).MakeGenericMethod(returnType)).Invoke(null, new object[] { cacheValue });
                    }
                    else
                    {
                        //context.ReturnValue = System.Convert.ChangeType(cacheValue.Value, context.ServiceMethod.ReturnType);
                        context.ReturnValue = cacheValue;
                    }
                }
                else
                {
                    // Invoke the method if we don't have a cache hit
                    await next(context);

                    if (isAvailable)
                    {
                        if (context.IsAsync())
                        {
                            //get the result
                            var returnValue = await context.UnwrapAsyncReturnValue();

                            await _cacheProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration));
                        }
                        else
                        {
                            await _cacheProvider.SetAsync(cacheKey, context.ReturnValue, TimeSpan.FromSeconds(attribute.Expiration));
                        }
                    }
                }
            }
            else
            {
                // Invoke the method if we don't have EasyCachingAbleAttribute
                await next(context);
            }
        }