Follow-up: Property Memento pattern

In a previous blog post I introduced the Property Memento pattern as way to temporarily save the value of an entity’s properties and restoring the initial values when the memento disposes.

While I like the pattern itself I think the syntax can be done better. Here comes an implementation that uses just one type parameter for the property type and misses the reflection helper. The static class PropertyMemento helps to generate PropertyMemento<T> instances without specifying the type parameter (it’s inferred by the compiler):

public class PropertyMemento<TProperty> : IDisposable
{
    private readonly TProperty _originalPropertyValue;
    private readonly object _classInstance;
    private readonly string _propertyName;

    public PropertyMemento(object classInstance,
        Expression<Func<TProperty>> propertySelector)
    {
        _classInstance = classInstance;
        _propertyName = ((MemberExpression)propertySelector.Body).Member.Name;
        _originalPropertyValue = GetPropertyValue();
    }

    public PropertyMemento(object classInstance,
        Expression<Func<TProperty>> propertySelector, TProperty tempValue)
        : this(classInstance, propertySelector)
    {
        SetPropertyValue(tempValue);
    }

    public void Dispose()
    {
        SetPropertyValue(_originalPropertyValue);
    }

    private TProperty GetPropertyValue()
    {
        return (TProperty)_classInstance
            .GetType()
            .GetProperty(_propertyName)
            .GetValue(_classInstance, null);
    }

    private void SetPropertyValue(TProperty value)
    {
        _classInstance
            .GetType()
            .GetProperty(_propertyName)
            .SetValue(_classInstance, value, null);
    }
}

public static class Memento
{
    public static PropertyMemento<TProperty> From<TProperty>(object classInstance,
        Expression<Func<TProperty>> propertySelector)
    {
        return new PropertyMemento<TProperty>(classInstance, propertySelector);
    }

    public static PropertyMemento<TProperty> From<TProperty>(object classInstance,
        Expression<Func<TProperty>> propertySelector, TProperty tempValue)
    {
        return new PropertyMemento<TProperty>(classInstance, propertySelector, tempValue);
    }
}

And now its usage in the same scenario shown in the original blog post:

private void SomeMethod(...)
{
    int oldValSumHeight = _valSum.Height;
    int newValSumHeight = 0;

    AnchorStyles newAnchor = AnchorStyles.Top | AnchorStyles.Left;
    using (PropertyMemento.From(_valSum, () => _valSum.AutoSize, true))
    using (PropertyMemento.From(_valSum, () => _valSum.Anchor, newAnchor))
    using (PropertyMemento.From(_detailContent, () => _detailContent.Anchor, newAnchor))
    {
        _valSum.SetValidationMessages(validationMessages);

        newValSumHeight = _valSum.Height;
        Height = Height - oldValSumHeight + newValSumHeight;
    }

    _valSum.Height = newValSumHeight;
}

As said before: just a little improvement to the original code which slightly improves the implementation and usage of the pattern…

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.