HTML5 Boilerplate Иконки

Как установить значение для свойства анонимного объекта?

blockquote>

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

Этот метод основан на конкретном соглашении, используемом компилятором для именования этих полей поддержки: i__Field в .NET и в Mono, с xxxxx, представляющим имя свойства. Если это соглашение должно было измениться, приведенный ниже код не сработает (обратите внимание: он также потерпит неудачу, если вы попытаетесь передать ему то, что не является анонимным типом).

public static class AnonymousObjectMutator
{
    private const BindingFlags FieldFlags = BindingFlags.NonPublic | BindingFlags.Instance;
    private static readonly string[] BackingFieldFormats = { "<{0}>i__Field", "<{0}>" };

    public static T Set(
        this T instance,
        Expression> propExpression,
        TProperty newValue) where T : class
    {
        var pi = (propExpression.Body as MemberExpression).Member;
        var backingFieldNames = BackingFieldFormats.Select(x => string.Format(x, pi.Name)).ToList();
        var fi = typeof(T)
            .GetFields(FieldFlags)
            .FirstOrDefault(f => backingFieldNames.Contains(f.Name));
        if (fi == null)
            throw new NotSupportedException(string.Format("Cannot find backing field for {0}", pi.Name));
        fi.SetValue(instance, newValue);
        return instance;
    }
}

Образец:

public static void Main(params string[] args)
{
    var myAnonInstance = new { 
        FirstField = "Hello", 
        AnotherField = 30, 
    };
    Console.WriteLine(myAnonInstance);

    myAnonInstance
        .Set(x => x.FirstField, "Hello SO")
        .Set(x => x.AnotherField, 42);
    Console.WriteLine(myAnonInstance);
}

С выходом:

{ FirstField = Hello, AnotherField = 30 }
{ FirstField = Hello SO, AnotherField = 42 }

Здесь можно найти несколько более сложную версию здесь

0
задан Alex 10 September 2012 в 13:30
поделиться