pátek 27. září 2013

Vylepšená třída PropertySupport z knihovny Prism

Microsoft nabízí na stránkách Codeplexu užitečnou knihovnu PRISM, kterou jistě každý WPFkový vývojář zná (ať už ji využívá nebo ne). Obsahuje šikovnou helper třídu PropertySupport s jedinou metodou ExtractPropertyName, která umí na základě zadané expresion vrátit název property ve třídě. Pokud se potřebujete v kódu odkázat na jméno property, tak to lze právě díky výše uvedené metodě udělat čistě bez nutnosti zanášet zdroják stringovými zápisy.

public class A {
    public string Foo { get; set; }

    public void Test() {
        System.Console.WriteLine("Trida A obsahuje propertu " + PropertySupport.ExtractPropertyName(() => Foo));

        var propertyName = "Foo";
        System.Console.WriteLine("Trida A obsahuje propertu " + propertyName)
    }
}

Nevýhodou je, že se takto dokážete odkázat pouze na property z třídy, ve které se na ní ptáte. Existuje ale možnost přidat overload metodu, která by uměla vrátit jméno property z libovolné třídy. Bohužel vývojářům PRISMu se tato nová metoda moc nelíbí, připadá jim, že porušuje Single Responsibility princip, takže nezbývá, než napsat vlastní třídu PropertySupport a tu si rozšířit dle potřeby.

public class PropertySupport
{
    public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
    {
        if (propertyExpression == null) {
            throw new ArgumentNullException("propertyExpression");
        }

        var memberExpression = propertyExpression.Body as MemberExpression;
        if (memberExpression == null) {
            throw new ArgumentException("The expression is not a member access expression.", "propertyExpression");
        }

        var property = memberExpression.Member as PropertyInfo;
        if (property == null) {
            throw new ArgumentException("The member access expression does not access a property.", "propertyExpression");
        }

        var getMethod = property.GetGetMethod(true);
        if (getMethod.IsStatic) {
            throw new ArgumentException("The referenced property is a static property.", "propertyExpression");
        }

        return memberExpression.Member.Name;
    }

    public static string ExtractPropertyName<TPropertyType, TClassType>(Expression<Func<TClassType, TClassType, TPropertyType>> propertyExpression)
    {
        if (propertyExpression == null) {
            throw new ArgumentNullException("propertyExpression");
        }

        var memberExpression = propertyExpression.Body as MemberExpression;
        if (memberExpression == null) {
            throw new ArgumentException("The expression is not a member access expression.", "propertyExpression");
        }

        var property = memberExpression.Member as PropertyInfo;
        if (property == null) {
            throw new ArgumentException("The member access expression does not access a property.", "propertyExpression");
        }

        var getMethod = property.GetGetMethod(true);
        if (getMethod.IsStatic) {
            throw new ArgumentException("The referenced property is a static property.", "propertyExpression");
        }

        return memberExpression.Member.Name;
    }
}

Poté je možné využít novou overload metodu následujícím způsobem. Jistě uznám, není to tak přímočarý a jednoduchý zápis jako v prvním příkladě, ale jednoduchost není všechno, že :-).

public class A {
    public string Foo { get; set; }

    public void Test() {
        System.Console.WriteLine("Trida A obsahuje propertu " + PropertySupport.ExtractPropertyName(() => Foo));

        System.Console.WriteLine("Trida B obsahuje propertu " + PropertySupport.ExtractPropertyName((x, y) => x.Boo))
    }
}

public class B {
    public string Boo { get; set; }
}

Třeba se někomu takové řešení hodí, stejně jako mě.

Žádné komentáře:

Okomentovat