Обновить универсальное свойство универсального класса? - PullRequest
1 голос
/ 26 января 2011

Я довольно новичок в C # Generic Classes, поэтому я не знаю, можем ли мы динамически обновлять универсальное свойство универсального класса?

Допустим, у меня есть класс

A { long id; long count; }

Можем ли мы написать расширение, которое обновит данное свойство на 1, так что

A.AddOne(a => a.id); will change A {id=1, count=1} to A {id=2, count=1}

and

A.AddOne(a => a.count); will change A {id=1, count=1} to A {id=1, count=2}

Любая помощь будет оценена!

1 Ответ

5 голосов
/ 26 января 2011

Если я правильно понимаю ваш вопрос, вы хотите иметь возможность объявить, какое свойство обновлять, передав лямбда-выражению методу AddOne.В этом случае это возможно - вы можете написать метод расширения, который принимает Expression<T>, извлекает из этого выражения выражение доступа к свойству и использует Reflection для обновления этого свойства объекта A.

Ниже приведен очень грубый прототип вышеописанного:

public static void AddOne<S,T>(this S x, Expression<Func<S,T>> expr)
{
    if (expr.Body.NodeType != ExpressionType.MemberAccess)
        throw new InvalidOperationException();

    MemberExpression memberExpr = expr.Body as MemberExpression;
    switch (memberExpr.Member.MemberType)
    {
        case MemberTypes.Field:
            {
                FieldInfo field = memberExpr.Member as FieldInfo;
                ulong value = Convert.ToUInt64(field.GetValue(x));
                ++value;
                field.SetValue(x, Convert.ChangeType(value, field.FieldType));
                break;
            }
        case MemberTypes.Property:
            {
                PropertyInfo prop = memberExpr.Member as PropertyInfo;
                ulong value = Convert.ToUInt64(prop.GetValue(x, null));
                ++value;
                prop.SetValue(x, Convert.ChangeType(value, prop.PropertyType), null);
                break;
            }
        default:
            throw new InvalidOperationException();
    }
}
...