Я реализую АОП для метода задачи. В 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; }
}