Autofa c реализует отчет об ошибках AOP-кэша для метода задачи - PullRequest
1 голос
/ 14 марта 2020

Я реализую АОП для метода задачи. В AOP я реализую логи c кеша. Перед выполнением метода я ввожу лог c AOP, чтобы определить, есть ли кеш. Если ударил кеш, я его прямо возвращаю. Если кэш не обработан, я выполняю метод, а затем вставляю результат выполнения метода в кеш. Однако при попадании в кеш я сообщаю о следующей ошибке

  InnerException    
{"Unable to cast object of type 'System.Threading.Tasks.Task`1[System.Object]' to type 
'System.Threading.Tasks.Task`1[System.Collections.Generic.List`1[cooperation_error_typeModel]]'."}  
System.Exception {System.InvalidCastException}

    /// <summary>
    /// 
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, Inherited = false)]
    public class CacheAttribute: Attribute
    {
        /// <summary>
        /// 
        /// </summary>
        public int ExpirationSeconds { get; }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="expirationSeconds"></param>
        public CacheAttribute(int expirationSeconds)
        { 
            this.ExpirationSeconds = expirationSeconds;
        }
    }


    [Intercept(typeof(CacheInterceptor))]
    [Repository]
    public class CoopErrorTypeRepository : ICoopErrorTypeRepository
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="coopId"></param>
        /// <returns></returns>
        [Cache(300)]
        public async Task<IEnumerable<cooperation_error_typeModel>> GetCoopErrorTypeList(string coopId)
        {
          return new cooperation_error_typeModel();
        }
    }

       public class CacheInterceptor : IInterceptor
    {
        /// <summary>
        /// Intercept
        /// </summary>
        /// <param name="invocation"></param>
        public void Intercept(IInvocation invocation)
        {
            var method = invocation.MethodInvocationTarget ?? invocation.Method;
            var cacheAttribute = this.GetQCachingAttributeInfo(method);
            if (cacheAttribute != null)
            {
                ProceedCaching(invocation, cacheAttribute, method);
            }
            else
            {
                invocation.Proceed();
            }
        }

        private CacheAttribute GetQCachingAttributeInfo(MethodInfo method)
        {
            return method.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(CacheAttribute)) as CacheAttribute;
        }

        private void ProceedCaching(IInvocation invocation, CacheAttribute attribute, MethodInfo method)
        { 
            var cacheKey = GetCacheKey(invocation.Arguments); 
            var client = RedisHelper.redisClientFactory.GetClient("CooperationDataCache"); 
            var cacheValue = client.String.Get(cacheKey); 
            if (!string.IsNullOrWhiteSpace(cacheValue))
            {
                if (method.ReturnType.BaseType == (typeof(Task)))
                {
                    Type[] genericTypeArguments = method.ReturnType.GenericTypeArguments;
                    if (genericTypeArguments != null && genericTypeArguments.Length > 0)
                    {
                        invocation.ReturnValue = Task.FromResult(JsonConvert.DeserializeObject(cacheValue, genericTypeArguments[0]));
                    }
                }
            }
            else
            {
                invocation.Proceed();

                if (method.ReturnType.BaseType == (typeof(Task)))
                {

                    //if (!(method.Invoke(invocation.InvocationTarget, invocation.Arguments) is Task task)) return;
                    var task = (Task)invocation.ReturnValue;
                    task.ContinueWith(m =>
                                {
                                    if (task.Status != TaskStatus.RanToCompletion) return;
                                    var result = ConvertHelperExtend.PackJson(((dynamic)task).Result);
                                    client.String.Set(cacheKey, result);
                                    client.Key.Expire(cacheKey, attribute.ExpirationSeconds);
                                });
                }
                else
                {
                    client.String.Set(cacheKey, ConvertHelperExtend.PackJson(invocation.ReturnValue));
                    client.Key.Expire(cacheKey, attribute.ExpirationSeconds);
                }
            }
        }

        /// <summary>
        /// get cache key
        /// </summary>
        /// <param name="invocation"></param>
        /// <returns></returns>
        private string GetCacheKey(object[] arguments)
        {
            if (arguments == null || arguments.Length < 1) return string.Empty;

            foreach (var argument in arguments)
            {
                if (argument is IGetCacheKey cacheKeyObj)
                    return cacheKeyObj.CacheKey;
            }
            return string.Empty;
        }
    }


    /// <summary>
    /// cache key
    /// </summary>
    public interface IGetCacheKey
    {
        /// <summary>
        /// cache key
        /// </summary>
        string CacheKey { get; }
    }
...