8

私のプロジェクトには、プライベートセッターを持ついくつかのプロパティを設定できるようにしたいユニットテストがいくつかあります。現在、私はリフレクションとこの拡張メソッドを介してそれを行っています:

public static void SetPrivateProperty(this object sourceObject, string propertyName, object propertyValue)
{
    sourceObject.GetType().GetProperty(propertyName).SetValue(sourceObject, propertyValue, null);
}

私がこのようなTestObjectを持っていると仮定します:

public class TestObject
{
    public int TestProperty{ get; private set; }
}

次に、ユニットテストでこれを次のように呼び出すことができます。

myTestObject.SetPrivateProperty("TestProperty", 1);

ただし、コンパイル時にプロパティ名を検証したいので、次のように式を介してプロパティを渡せるようにします。

myTestObject.SetPrivateProperty(o => o.TestProperty, 1);

これどうやってするの?

4

2 に答える 2

9

ゲッターが公開されている場合、次のように動作するはずです。次のような拡張メソッドが提供されます。

var propertyName = myTestObject.NameOf(o => o.TestProperty);

public getter が必要です。いつか、このようなリフレクション機能が言語に組み込まれることを願っています。

public static class Name
{
    public static string Of(LambdaExpression selector)
    {
        if (selector == null) throw new ArgumentNullException("selector");

        var mexp = selector.Body as MemberExpression;
        if (mexp == null)
        {
            var uexp = (selector.Body as UnaryExpression);
            if (uexp == null)
                throw new TargetException(
                    "Cannot determine the name of a member using an expression because the expression provided cannot be converted to a '" +
                    typeof(UnaryExpression).Name + "'."
                );
            mexp = uexp.Operand as MemberExpression;
        }

        if (mexp == null) throw new TargetException(
            "Cannot determine the name of a member using an expression because the expression provided cannot be converted to a '" +
            typeof(MemberExpression).Name + "'."
        );
        return mexp.Member.Name;
    }

    public static string Of<TSource>(Expression<Func<TSource, object>> selector)
    {
        return Of<TSource, object>(selector);
    }

    public static string Of<TSource, TResult>(Expression<Func<TSource, TResult>> selector)
    {
        return Of(selector as LambdaExpression);
    }
}

public static class NameExtensions
{
    public static string NameOf<TSource, TResult>(this TSource obj, Expression<Func<TSource, TResult>> selector)
    {
        return Name.Of(selector);
    }
}
于 2012-04-17T14:49:42.143 に答える