Как я могу получить значения параметров из выражения lamba для моего отличного расширения кэша? - PullRequest
1 голос
/ 20 августа 2010

Прежде всего, возможно, стоит посмотреть на этот вопрос: Как я могу кешировать объекты в ASP.NET MVC?

Есть некоторый псевдокод, который почти выполняет то, что я хочу:1005 *

public class CacheExtensions
{
  public static T GetOrStore<T>(this Cache cache, string key, Func<T> generator)
  {
    var result = cache[key];
    if(result == null)
    {
      result = generator();
      cache[key] = result;
    }
     return (T)result;
   }
}

Однако то, что я действительно хотел бы сделать, это автоматически сгенерировать «ключ» из генератора.Я полагаю, что мне нужно изменить сигнатуру метода на:

public static T GetOrStore<T>(this Cache cache,
                System.Linq.Expressions.Expression<Func<T>> generator)

Я хочу использовать имя метода, но также любые параметры и их значения для генерации ключа.Я могу получить тело метода из выражения и имена параметров (вроде), но я понятия не имею, как получить значения параметров ...?

Или я поступаю неправильно?Любые идеи высоко ценится.

Ответы [ 2 ]

0 голосов
/ 31 января 2013

Вот как я это сделал:

public static class ICacheExtensions
{
    public static T GetOrAdd<T>(this ICache cache, Expression<Func<T>> getterExp)
    {
        var key = BuildCacheKey<T>(getterExp);
        return cache.GetOrAdd(key, () => getterExp.Compile().Invoke());
    }

    private static string BuildCacheKey<T>(Expression<Func<T>> getterExp)
    {
        var body = getterExp.Body;
        var methodCall = body as MethodCallExpression;
        if (methodCall == null)
        {
            throw new NotSupportedException("The getterExp must be a MethodCallExpression");
        }

        var typeName = methodCall.Method.DeclaringType.FullName;
        var methodName = methodCall.Method.Name;
        var arguments = methodCall.Arguments
            .Select(a => ExpressionHelper.Evaluate(a))
            .ToArray();

        return String.Format("{0}_{1}_{2}", 
            typeName, 
            methodName, 
            String.Join("|", arguments));
    }
  }

с помощью этого помощника для оценки узлов дерева выражений:

internal static class ExpressionHelper
    {
        public static object Evaluate(Expression e)
        {
            Type type = e.Type;
            if (e.NodeType == ExpressionType.Convert)
            {
                var u = (UnaryExpression)e;
                if (TypeHelper.GetNonNullableType(u.Operand.Type) == TypeHelper.GetNonNullableType(type))
                {
                    e = ((UnaryExpression)e).Operand;
                }
            }
            if (e.NodeType == ExpressionType.Constant)
            {
                if (e.Type == type)
                {
                    return ((ConstantExpression)e).Value;
                }
                else if (TypeHelper.GetNonNullableType(e.Type) == TypeHelper.GetNonNullableType(type))
                {
                    return ((ConstantExpression)e).Value;
                }
            }
            var me = e as MemberExpression;
            if (me != null)
            {
                var ce = me.Expression as ConstantExpression;
                if (ce != null)
                {
                    return me.Member.GetValue(ce.Value);
                }
            }
            if (type.IsValueType)
            {
                e = Expression.Convert(e, typeof(object));
            }
            Expression<Func<object>> lambda = Expression.Lambda<Func<object>>(e);
            Func<object> fn = lambda.Compile();
            return fn();
        }
    }
0 голосов
/ 20 августа 2010

При вызове функции, которая создает коллекцию, которую я хочу кэшировать, я передаю все параметры и имя моей функции в функцию кэширования, которая создает ключ из нее.

Все мои классы реализуют интерфейс, который имеетПоле идентификатора, чтобы я мог использовать его в своих ключах кеша.

Я уверен, что есть более приятный способ, но иногда я тоже сплю.можно использовать для аннулирования связанных коллекций.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...