如何通过lambda表达式传递属性?

8

我的项目有一些单元测试,我们希望能够设置一些具有私有setter属性的属性。目前我是通过反射和这个扩展方法来实现的:

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);

我该如何做到这一点?

Lambda表达式的目的是什么?是为了提供编译时验证吗? - mellamokb
@mellamokb 是的。如果有其他方法可以做到,我很乐意尝试。 - Sterno
请查看 https://dev59.com/-HRB5IYBdhLWcg3wSVYI。 - phoog
2个回答

9
如果getter是公共的,那么以下代码应该有效。它会给你一个扩展方法,看起来像这样:
var propertyName = myTestObject.NameOf(o => o.TestProperty);

这需要一个公共的 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);
    }
}

4

新手指南:C# 6.0 : nameof(property)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接