protected override void InterceptSync(IInvocation invocation)
        {
            CacheInterceptorContext context = null;

            context = GetCacheInterceptorContext(invocation);

            var key = BuildCacheKey(invocation, context);

            if (context.CacheAttr.Invalidate)
            {
                var prefix = context.CacheAttr.Prefix;
                if (string.IsNullOrWhiteSpace(prefix))
                {
                    prefix = context.ClassName;
                }
                CacheClient.RemoveByPrefixAsync(prefix).GetAwaiter().GetResult();

                base.InterceptSync(invocation);
            }
            else
            {
                var cacheResultTask = (dynamic)context.GetFromCacheMethodInfo.Invoke(CacheClient, new string[] { key });
                var cacheResult     = cacheResultTask.GetAwaiter().GetResult();
                if (cacheResult.HasValue)
                {
                    invocation.ReturnValue = cacheResult.Value;
                }
                else
                {
                    base.InterceptSync(invocation);
                    //ADD to cache
                    AddToCache(context, key, invocation.ReturnValue);
                }
            }
        }
        protected virtual string BuildCacheKey(IInvocation invocation, CacheInterceptorContext context)
        {
            var sb = new StringBuilder();

            if (!string.IsNullOrWhiteSpace(context.CacheAttr.Prefix))
            {
                sb.Append(context.CacheAttr.Prefix);
            }
            else
            {
                sb.Append(context.ClassName);
                sb.Append(".");
                sb.Append(context.MethodName);
            }
            if (context.CacheAttr.IsUserContextAware && ActionContext.Data.ContainsKey("UserId"))
            {
                var userId = ActionContext.Data["UserId"].ToString();
                sb.Append(".u." + userId);
            }
            sb.Append(":");
            string output = JsonConvert.SerializeObject(invocation.Arguments, jsonSerializerSettings);

            sb.Append(output);
            return(sb.ToString());
        }
 private void AddToCache(CacheInterceptorContext context, string key, object result)
 {
     if (context.CacheAttr.ExpirationType == ExpirationType.Default)
     {
         CacheClient.AddAsync(key, result).GetAwaiter().GetResult();
     }
     else if (context.CacheAttr.ExpirationType == ExpirationType.ExpiresIn)
     {
         TimeSpan span = TimeSpan.Parse(context.CacheAttr.ExpirationPattern);
         CacheClient.AddAsync(key, result, span).GetAwaiter().GetResult();
     }
 }
        private CacheInterceptorContext GetCacheInterceptorContext(IInvocation invocation)
        {
            CacheInterceptorContext context;

            if (!MethodList.TryGetValue(invocation.Method, out context))
            {
                lock (_lock)
                {
                    context            = new CacheInterceptorContext();
                    context.MethodName = invocation.Method.Name;
                    context.ClassName  = invocation.TargetType.FullName;
                    context.CacheAttr  = invocation.Method.GetCustomAttribute <CacheAttribute>();

                    var methodType = invocation.Method.ReturnType;
                    if (methodType.IsGenericType)
                    {
                        context.GetFromCacheMethodInfo = typeof(ICacheClient).GetMethod("GetAsync")
                                                         .MakeGenericMethod(new Type[] { methodType.GetGenericArguments()[0] });

                        var task = Task.FromResult <object>(null);

                        Type taskReturnType = (context.GetFromCacheMethodInfo).ReturnType;                //e.g. Task<int>

                        var type = taskReturnType.GetGenericArguments()[0].GetGenericArguments()[0];      //get the result type, e.g. int

                        var convert_method = this.GetType().GetMethod("Convert").MakeGenericMethod(type); //Get the closed version of the Convert method, e.g. Convert<int>
                        context.CreateNewInstanceMethodInfo = convert_method;
                    }
                    else
                    {
                        context.GetFromCacheMethodInfo = typeof(ICacheClient).GetMethod("GetAsync")
                                                         .MakeGenericMethod(new Type[] { methodType });
                    }

                    if (MethodList.ContainsKey(invocation.Method))
                    {
                        MethodList[invocation.Method] = context;
                    }
                    else
                    {
                        MethodList.Add(invocation.Method, context);
                    }
                }
            }

            return(context);
        }