How can I pass a property in via a lambda expressi

2019-04-06 21:59发布

There are some unit tests on my project where we want to be able to set some properties that have private setters. Currently I'm doing it via reflection and this extension method:

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

Assuming I had a TestObject like this:

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

I can then call this in my unit tests as follows:

myTestObject.SetPrivateProperty("TestProperty", 1);

However, I'd like to have validation of the property name at compile time, and thus I'd like to be able to pass the property in via expression, like this:

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

How can I do this?

标签: c# lambda
2条回答
成全新的幸福
2楼-- · 2019-04-06 22:26

New to C# 6.0 : nameof(property)

查看更多
太酷不给撩
3楼-- · 2019-04-06 22:46

If the getter is public, then the following should work. It will give you an extension method that looks like this:

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

It requires a public getter. I hope, at some point, reflection functionality like this is rolled into the language.

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);
    }
}
查看更多
登录 后发表回答