private async Task ProcessGetOrCreateAsync(AspectContext context, AspectDelegate next)
        {
            if (GetMethodAttributes(context.ServiceMethod) is EniymCacheGetOrCreateAttribute attribute)
            {
                if (string.IsNullOrEmpty(attribute.Template))
                {
                    throw new ArgumentNullException($"please set the cache key '{nameof(attribute.Template)}'");
                }

                var returnType = context.IsAsync()
                    ? context.ServiceMethod.ReturnType.GetGenericArguments().First()
                    : context.ServiceMethod.ReturnType;

                var cacheKey = KeyGenerator.GetCacheKey(context, attribute.Template);
                Logger.LogInformation($"KeyGenerator.GetCacheKey: '{cacheKey}'");

                object cacheValue = null;
                try
                {
                    cacheValue = await CacheProvider.GetAsync(cacheKey, returnType);
                }
                catch
                {
                    Logger.LogError($"An error occurred while reading cache '{cacheKey}'.");
                    cacheValue = null;
                }

                if (cacheValue != null)
                {
                    context.ReturnValue = context.IsAsync()
                        ? TaskResultMethod
                                          .GetOrAdd(returnType,
                                                    t => typeof(Task).GetMethods()
                                                    .First(p => p.Name == "FromResult" && p.ContainsGenericParameters)
                                                    .MakeGenericMethod(returnType)).Invoke(null, new object[] { cacheValue })
                        : cacheValue;
                }
                else
                {
                    await next(context);

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

                    if (returnValue != null)
                    {
                        await CacheProvider.SetAsync(cacheKey, returnValue, attribute.CacheSeconds);
                    }
                }
            }
            else
            {
                await next(context);
            }
        }
Example #2
0
        public async override Task Invoke(AspectContext context, AspectDelegate next)
        {
            Assert.False(context.IsAsync());
            await context.Invoke(next);

            Assert.True(context.IsAsync());
            var result = context.UnwrapAsyncReturnValue();

            Assert.Equal(100, result);
        }
Example #3
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 (context.ServiceMethod.GetCustomAttributes(true).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 = await CacheProvider.GetAsync(cacheKey, returnType);

                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 (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);
            }
        }
        private async Task DoCaching(
            AspectContext context,
            AspectDelegate next,
            CachingAttribute cachingAttribute
            )
        {
            var cacheProvider = context.ServiceProvider.GetService(typeof(ICachingProvider)) as ICachingProvider;

            var    cachingKey = GenerateCachingKey(context, cachingAttribute);
            object cacheValue = await cacheProvider.GetAsync <object>(cachingKey);

            if (cacheValue != null)// 若读取到缓存就直接返回,否则设置缓存
            {
                if (context.IsAsync())
                {
                    PropertyInfo propertyInfo = context.ServiceMethod.ReturnType.GetMember("Result")[0] as PropertyInfo;
                    dynamic      returnValue  = JsonConvert.DeserializeObject(cacheValue.ToString(), propertyInfo.PropertyType);

                    context.ReturnValue = Task.FromResult(returnValue);
                }
                else
                {
                    context.ReturnValue = JsonConvert.DeserializeObject(cacheValue.ToString(), context.ServiceMethod.ReturnType);
                }
            }
            else
            {
                await next(context);

                // 设置缓存
                if (!string.IsNullOrWhiteSpace(cachingKey))
                {
                    object returnValue = null;

                    if (context.IsAsync())
                    {
                        returnValue = await context.UnwrapAsyncReturnValue();
                    }
                    else
                    {
                        returnValue = context.ReturnValue;
                    }

                    await cacheProvider.SetAsync(
                        cachingKey,
                        returnValue,
                        TimeSpan.FromSeconds(cachingAttribute.Expiration)
                        );
                }
            }
        }
Example #5
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)
        {
            var attribute = context.ServiceMethod.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(EasyCachingAbleAttribute)) as EasyCachingAbleAttribute;

            if (attribute != null)
            {
                var cacheKey   = KeyGenerator.GetCacheKey(context.ServiceMethod, context.Parameters, attribute.CacheKeyPrefix);
                var cacheValue = await CacheProvider.GetAsync <object>(cacheKey);

                if (cacheValue.HasValue)
                {
                    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
                        //...
                    }
                    else
                    {
                        context.ReturnValue = System.Convert.ChangeType(cacheValue.Value, context.ServiceMethod.ReturnType);
                    }
                }
                else
                {
                    // Invoke the method if we don't have a cache hit
                    await next(context);

                    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);
            }
        }
Example #6
0
        public override async Task Invoke(AspectContext context, AspectDelegate next)
        {
            var logger = LogManager.GetLogger("ProxyInterceptor");

            var parameters = JsonConvert.SerializeObject(context.Parameters);

            logger.Info($"Call api {context.ServiceMethod.DeclaringType.FullName}->{context.ServiceMethod.Name} Paramters:{parameters}");

            await next(context);

            if (context.IsAsync())
            {
                if (context.ServiceMethod.ReturnType.FullName == "System.Threading.Tasks.Task")
                {
                    logger.Info($"Result value: void");
                }
                else
                {
                    var result = await context.UnwrapAsyncReturnValue();

                    var res = JsonConvert.SerializeObject(result);
                    logger.Info($"Result value: {res}");
                }
            }
            else
            {
                if (context.ReturnValue != null)
                {
                    var res = JsonConvert.SerializeObject(context.ReturnValue);
                    logger.Info($"Result value: {res}");
                }
            }
        }
        public async override Task Invoke(AspectContext context, AspectDelegate next)
        {
            var Parameters = context.Parameters;
            await context.Invoke(next);

            var result = context.IsAsync() ? await context.UnwrapAsyncReturnValue(): context.ReturnValue;
        }
        public async override Task Invoke(AspectContext context, AspectDelegate next)
        {
            if (_cacheType.GetInterfaces().Contains(typeof(IDistributedCache)))
            {
            }

            //判断是否是异步方法
            bool isAsync = context.IsAsync();
            //if (context.ImplementationMethod.GetCustomAttribute(typeof(System.Runtime.CompilerServices.AsyncStateMachineAttribute)) != null)
            //{
            //    isAsync = true;
            //}
            //先判断方法是否有返回值,无就不进行缓存判断
            Type methodReturnType = context.GetReturnParameter().Type;

            if (methodReturnType == typeof(void) || methodReturnType == typeof(Task) || methodReturnType == typeof(ValueTask))
            {
                await next(context);

                return;
            }
            Type returnType = methodReturnType;

            if (isAsync)
            {
                //取得异步返回的类型
                returnType = returnType.GenericTypeArguments.FirstOrDefault();
            }
            //获取方法参数名
            //string param = CommonHelper.ObjectToJsonString(context.Parameters);
            ////获取方法名称,也就是缓存key值
            //string key = "Methods:" + context.ImplementationMethod.DeclaringType.FullName + "." + context.ImplementationMethod.Name;
            //var cache = context.ServiceProvider.GetService<ICacheHelper>();
        }
        /// <summary>
        /// Processes the put async.
        /// </summary>
        /// <returns>The put async.</returns>
        /// <param name="context">Context.</param>
        private async Task ProcessPutAsync(AspectContext context)
        {
            if (GetMethodAttributes(context.ServiceMethod).FirstOrDefault(x => x.GetType() == typeof(EasyCachingPutAttribute)) is EasyCachingPutAttribute attribute && context.ReturnValue != null)
            {
                var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName);
                var cacheKey       = KeyGenerator.GetCacheKey(context.ServiceMethod, context.Parameters, attribute.CacheKeyPrefix);

                try
                {
                    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));
                    }
                }
                catch (Exception ex)
                {
                    if (!attribute.IsHightAvailability)
                    {
                        throw;
                    }
                    else
                    {
                        Logger?.LogError(new EventId(), ex, $"Cache provider \"{_cacheProvider.Name}\" set error.");
                    }
                }
            }
        }
Example #10
0
        /// <summary>
        /// 执行被拦截方法
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        private async Task <object> RunAndGetReturn(AspectContext context, AspectDelegate next)
        {
            await context.Invoke(next);

            return(context.IsAsync()
            ? await context.UnwrapAsyncReturnValue()
            : context.ReturnValue);
        }
        public override async Task Invoke(AspectContext context, AspectDelegate next)
        {
            var parameters = context.ServiceMethod.GetParameters();

            //判断Method是否包含ref / out参数
            if (parameters.Any(it => it.IsIn || it.IsOut))
            {
                await next(context);
            }
            else
            {
                var key = string.IsNullOrEmpty(CacheKey)
                     ? new CacheKey(context.ServiceMethod, parameters, context.Parameters).GetMemoryCacheKey()
                     : CacheKey;
                //返回值类型
                var returnType = context.IsAsync()
                    ? context.ServiceMethod.ReturnType.GetGenericArguments().First()
                    : context.ServiceMethod.ReturnType;
                if (_cache.TryGetValue(key, out object value))
                {
                    context.ReturnValue = context.IsAsync()
                   ? _taskResultMethod.MakeGenericMethod(returnType).Invoke(null, new object[] { value })
                   : value;
                    return;
                }
                else
                {
                    await context.Invoke(next);

                    object returnValue = context.ReturnValue;
                    if (context.ServiceMethod.IsReturnTask())
                    {
                        returnValue = returnValue.GetPropertyValue("Result");
                    }

                    _cache.Set(key, returnValue, new MemoryCacheEntryOptions()
                    {
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(Expiration)
                    });
                    //await next(context);
                }
            }
        }
Example #12
0
        /// <summary>
        /// 获取缓存,并处理返回值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="type"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        private object GetCahceValue(string key, Type type, AspectContext context)
        {
            //从缓存取值
            var cacheValue = CacheProvider.Get(key, type);

            if (cacheValue != null)
            {
                context.ReturnValue = context.IsAsync()
                    ? TaskResultMethod.MakeGenericMethod(type).Invoke(null, new object[] { cacheValue })
                    : cacheValue;
            }
            return(cacheValue);
        }
        public override async Task Invoke(AspectContext context, AspectDelegate next)
        {
            var validator = (MethodInvocationValidator)context.ServiceProvider.GetService(typeof(MethodInvocationValidator));

            MethodInfo method;

            try
            {
                method = context.ImplementationMethod;
            }
            catch
            {
                method = context.ServiceMethod;
            }
            var failures = validator.Validate(method, context.Parameters);

            var result = failures.ToResult();

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

                return;
            }

            if (context.IsAsync())
            {
                if (context.ImplementationMethod.ReturnType == typeof(Task))
                {
                    ThrowValidationException(result);
                    //throw new Exception(result.Data.Select(o=>o.Message).ToJoin());
                }
                else
                {
                    var returnType = context.ImplementationMethod.ReturnType.GenericTypeArguments[0];
                    if (typeof(IResultBase).IsAssignableFrom(returnType))
                    {
                        context.ReturnValue = Task.FromResult(new OperationResponse()
                        {
                            Message = result.Message.IsNullOrEmpty() ? result.Data.Select(o => o.Message).ToJoin() : result.Message,
                            Type    = Enums.OperationResponseType.Error
                        });
                    }
                    else
                    {
                        ThrowValidationException(result);
                    }
                    //ThrowValidationException(result);
                }
            }
        }
Example #14
0
        public async override Task Invoke(AspectContext context, AspectDelegate next)
        {
            try
            {
                string key = string.Empty;
                //自定义的缓存key不存在,再获取类名+方法名或类名+方法名+参数名的组合式key
                if (!string.IsNullOrEmpty(_cacheKey))
                {
                    key = _cacheKey;
                }
                else
                {
                    key = GetKey(context.ServiceMethod, context.Parameters);
                }

                var    returnType = GetReturnType(context);
                var    cache      = context.ServiceProvider.GetService <ICacheHelper>();
                object result     = null;
                if (cache.Exists(key))
                {
                    var strResult = cache.Get(key);
                    result = strResult;
                }

                if (result != null)
                {
                    context.ReturnValue = ResultFactory(result, returnType, context.IsAsync());
                }
                else
                {
                    result = await RunAndGetReturn(context, next);

                    if (_expireSecond > 0)
                    {
                        cache.Set(key, result, TimeSpan.FromMinutes(_expireSecond));
                    }
                    else
                    {
                        cache.Set(key, result);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                throw e;
            }
        }
        /// <summary>
        /// 执行后
        /// </summary>
        /// <param name="log">日志操作</param>
        /// <param name="context">Aspect上下文</param>
        /// <param name="methodName">方法名</param>
        private async Task ExecuteAfter(ILog log, AspectContext context, string methodName)
        {
            if (context.ServiceMethod.ReturnType == typeof(Task) ||
                context.ServiceMethod.ReturnType == typeof(void) ||
                context.ServiceMethod.ReturnType == typeof(ValueTask))
            {
                return;
            }
            var returnValue = context.IsAsync() ? await context.UnwrapAsyncReturnValue() : context.ReturnValue;

            var returnType = returnValue.GetType().FullName;

            log.Caption($"{context.ServiceMethod.Name}方法执行后")
            .Method(methodName)
            .Content($"返回类型: {returnType}, 返回值: {returnValue.SafeString()}");
            WriteLog(log);
        }
Example #16
0
        public async override Task Invoke(AspectContext context, AspectDelegate next)
        {
            var cachedConfigurationProvider = context.ServiceProvider.GetService <IOptionsMonitor <FilterCachedConfiguration> >();
            var configCache = context.GetCacheConfigurationByMethodName(cachedConfigurationProvider.CurrentValue);

            var methodReturnType = context.ProxyMethod.ReturnType;

            if (
                configCache == null ||
                methodReturnType == typeof(void) ||
                methodReturnType == typeof(Task) ||
                methodReturnType == typeof(ValueTask)
                )
            {
                await next(context);

                return;
            }

            if (string.IsNullOrWhiteSpace(CacheName))
            {
                CacheName = context.GetGenerateKeyByMethodNameAndValues();
            }

            ResponseCacheService = context.ServiceProvider.GetService <IResponseCacheService>();

            var returnType = context.IsAsync() ? methodReturnType.GenericTypeArguments.FirstOrDefault() : methodReturnType;

            var cachedValue = await ResponseCacheService.GetCachedResponseAsync(CacheName, returnType);

            if (cachedValue != null)
            {
                context.SetReturnType(methodReturnType, cachedValue);
                return;
            }

            await next(context);

            await ResponseCacheService
            .SetCacheResponseAsync(
                CacheName,
                await context.GetReturnValueAsync(),
                TimeSpan.FromSeconds(configCache.TimeToLiveSeconds ?? TimeToLiveSeconds)
                );
        }
        public async override Task Invoke(AspectContext context, AspectDelegate next)
        {
            if (!IsOpen || Seconds <= 0)
            {
                await next(context);

                return;
            }

            try
            {
                var cacheService = context.ServiceProvider.GetService <ICacheService>();

                Type returnType = context.GetReturnType();

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

                var result = cacheService.Get(key, returnType);

                if (result == null)
                {
                    await next(context);

                    var value = await context.GetReturnValue();

                    if (value != null)
                    {
                        cacheService.Set(key, TimeSpan.FromSeconds(Seconds), value);
                    }
                }
                else
                {
                    context.ReturnValue = context.ResultFactory(result, returnType, context.IsAsync());
                }
            }
            catch (Exception ex)
            {
                var logger = context.ServiceProvider.GetService <ILogger <CacheMethodAttribute> >();

                logger.LogError($"CacheMethod:Key:{Key},ParamterKey:{ParamterKey} {ex.FormatMessage()}");

                await next(context);
            }
        }
 public static void SetReturnType(this AspectContext context, Type methodReturnType, object value)
 {
     if (context.IsAsync())
     {
         var returnType = methodReturnType.GenericTypeArguments.FirstOrDefault();
         if (methodReturnType == typeof(Task <>).MakeGenericType(returnType))
         {
             context.ReturnValue = typeof(Task).GetMethod(nameof(Task.FromResult)).MakeGenericMethod(returnType).Invoke(null, new[] { value });
         }
         else if (methodReturnType == typeof(ValueTask <>).MakeGenericType(returnType))
         {
             context.ReturnValue = Activator.CreateInstance(typeof(ValueTask <>).MakeGenericType(returnType), value);
         }
     }
     else
     {
         context.ReturnValue = value;
     }
 }
        /// <summary>
        /// Processes the put async.
        /// </summary>
        /// <returns>The put async.</returns>
        /// <param name="context">Context.</param>
        private async Task ProcessPutAsync(AspectContext context)
        {
            if (context.ServiceMethod.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(EasyCachingPutAttribute)) is EasyCachingPutAttribute attribute && context.ReturnValue != null)
            {
                var cacheKey = KeyGenerator.GetCacheKey(context.ServiceMethod, context.Parameters, attribute.CacheKeyPrefix);

                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));
                }
            }
        }
Example #20
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public override async Task Invoke(AspectContext context, AspectDelegate next)
        {
            if (context.ServiceMethod.AttributeExists <DisableUnitOfWorkAttribute>() || context.ImplementationMethod.AttributeExists <DisableUnitOfWorkAttribute>())
            {
                await next(context);

                return;
            }
            using (var uow = _unitOfWorkManager.Begin(CreateOptions(context)))
            {
                await next(context);

                if (context.IsAsync())
                {
                    await uow.CompleteAsync();
                }
                else
                {
                    uow.Complete();
                }
            }
        }
Example #21
0
        public async override Task Invoke(AspectContext context, AspectDelegate next)
        {
            if (!IsOpen)
            {
                await next(context);

                return;
            }

            try
            {
                var cacheService = context.ServiceProvider.GetService <ICacheService>();

                Type returnType = context.GetReturnType();

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

                var result = cacheService.Get(key, returnType);

                if (result == null)
                {
                    await Next(context, next, cacheService, key);
                }
                else
                {
                    context.ReturnValue = context.ResultFactory(result, returnType, context.IsAsync());
                }
            }
            catch (Exception ex)
            {
                var logger = context.ServiceProvider.GetService <ILogger <CacheTiggerAttribute> >();

                logger.LogError($"CacheInterceptor:Key:{Key},ParamterKey:{ParamterKey} {ex.FormatMessage()}");

                await next(context);
            }
        }
Example #22
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);
                }
            }
        }
        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);
                }
            }
        }
 /// <summary>
 /// 获取被拦截方法返回值类型
 /// </summary>
 /// <param name="context"></param>
 /// <returns></returns>
 private Type GetReturnType(AspectContext context)
 {
     return(context.IsAsync()
         ? context.ServiceMethod.ReturnType.GetGenericArguments().First()
         : context.ServiceMethod.ReturnType);
 }
 private object buildResult(AspectContext context)
 {
     return(context.IsAsync() ? context.UnwrapAsyncReturnValue().Result : context.ReturnValue);
 }
 public static Type GetReturnType(this AspectContext context)
 {
     return(context.IsAsync()
                                 ? context.ServiceMethod.ReturnType.GetGenericArguments().First()
                                 : context.ServiceMethod.ReturnType);
 }
 public async static Task <object> GetReturnValueAsync(this AspectContext context)
 => context.IsAsync() ?
 await context.UnwrapAsyncReturnValue() :
 context.ReturnValue;
        /// <summary>
        ///
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        private async Task ProcessRedisCaching(AspectContext context, AspectDelegate next)
        {
            var attribute = GetMethodAttributes(context.ServiceMethod).FirstOrDefault(x => x.GetType() == typeof(RedisCachingAttribute)) as RedisCachingAttribute;

            if (attribute == null)
            {
                await context.Invoke(next);
            }
            var returnType = context.IsAsync()
                    ? context.ServiceMethod.ReturnType.GetGenericArguments().First()
                    : context.ServiceMethod.ReturnType;
            var cacheKey = "";

            cacheKey = KeyGenerator.GetCacheKey(context.ServiceMethod, context.Parameters, attribute.CacheKeyPrefix);
            if (context.Parameters != null && context.Parameters.Length > 0)
            {
                var md5key = Encrypt.Md5By32(Json.ToJson(context.Parameters));
                cacheKey = cacheKey + ":" + md5key;
            }
            else
            {
                var md5key = Encrypt.Md5By32(Json.ToJson(context.ServiceMethod.Name));
                cacheKey = cacheKey + ":" + md5key;
            }
            object cacheValue  = null;
            var    isAvailable = true;

            try
            {
                if (attribute.IsHybridProvider)
                {
                    cacheValue = await HybridCachingProvider.GetAsync(cacheKey, returnType);
                }
                else
                {
                    var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName);
                    //cacheValue = await _cacheProvider.GetAsync(cacheKey, returnType);
                    var val = await _cacheProvider.GetAsync <string>(cacheKey);

                    if (val.HasValue)
                    {
                        cacheValue = JsonConvert.DeserializeObject(val.Value, returnType);
                    }
                }
            }
            catch (Exception ex)
            {
                if (!attribute.IsHighAvailability)
                {
                    throw ex;
                }
                else
                {
                    isAvailable = false;
                }
            }

            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;
                }
                return;
            }
            // Invoke the method if we don't have a cache hit
            await next(context);

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

                    // should we do something when method return null?
                    // 1. cached a null value for a short time
                    // 2. do nothing
                    if (returnValue != null && cacheKey.IsNotWhiteSpaceEmpty())
                    {
                        if (attribute.IsHybridProvider)
                        {
                            await HybridCachingProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration));
                        }
                        else
                        {
                            var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName);
                            //var f = Newtonsoft.Json.JsonConvert.SerializeObject(returnValue);
                            await _cacheProvider.SetAsync(cacheKey, JsonConvert.SerializeObject(returnValue, new JsonSerializerSettings()
                            {
                                NullValueHandling = NullValueHandling.Ignore, DateTimeZoneHandling = DateTimeZoneHandling.Local
                            }), TimeSpan.FromSeconds(attribute.Expiration));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ex.Submit();
            }
        }
Example #29
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 => typeof(EasyCachingAbleAttribute).IsAssignableFrom(x.GetType())) 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
                {
                    if (attribute.IsHybridProvider)
                    {
                        cacheValue = await HybridCachingProvider.GetAsync(cacheKey, returnType);
                    }
                    else
                    {
                        var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName);
                        cacheValue = await _cacheProvider.GetAsync(cacheKey, returnType);
                    }
                }
                catch (Exception ex)
                {
                    if (!attribute.IsHighAvailability)
                    {
                        throw;
                    }
                    else
                    {
                        isAvailable = false;
                        Logger?.LogError(new EventId(), ex, $"Cache provider 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)
                    {
                        // get the result
                        var returnValue = context.IsAsync()
                            ? await context.UnwrapAsyncReturnValue()
                            : context.ReturnValue;

                        // should we do something when method return null?
                        // 1. cached a null value for a short time
                        // 2. do nothing
                        if (returnValue != null)
                        {
                            if (attribute.IsHybridProvider)
                            {
                                await HybridCachingProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration));
                            }
                            else
                            {
                                var _cacheProvider = CacheProviderFactory.GetCachingProvider(attribute.CacheProviderName ?? Options.Value.CacheProviderName);
                                await _cacheProvider.SetAsync(cacheKey, returnValue, TimeSpan.FromSeconds(attribute.Expiration));
                            }
                        }
                    }
                }
            }
            else
            {
                // Invoke the method if we don't have EasyCachingAbleAttribute
                await next(context);
            }
        }
 public static async Task <object> GetReturnValue(this AspectContext context)
 {
     return(context.IsAsync() ? await context.UnwrapAsyncReturnValue() : context.ReturnValue);
 }