是否有更简洁的方法来设置通用类的属性?

时间:2017-04-29 06:05:30

标签: c# expression-trees anonymous-types c#-7.0

这是我到目前为止所做的,它运作正常。我只是想知道是否有更顺畅的方法:

    public static PropertyInfo GetProperty<T, T2>(this Expression<Func<T, T2>> selectorExpression)
    {
        var memberExpression = selectorExpression.Body as MemberExpression;
        if (memberExpression == null) throw new InvalidCastException();

        return memberExpression.Member as PropertyInfo;
    }

这是一个现在可以使用它的示例函数。这个将把列表中对象的所有选定值设置为某个值。

    public static List<T> Set<T,T2>(this List<T> inList, decimal amount, Expression<Func<T, decimal>> valueSelector)
        where T : class
    {
        var valueProperty = valueSelector.GetProperty();

        foreach (var item in inList)
        {
            valueProperty.SetValue(item, amount);
        }

        return inList
    }

然后我可以这样做:

myList.Set(100, i => i.Value);

其中Value是MyList中对象的某些Setter属性。

现在我知道第二个功能是一个非常简单的例子。我实际上 使用GetProperty来处理更复杂的东西,特别是我编写了一个函数,根据其中的Getter'weight'属性将IEnumerable中的值除以选定的setter属性。< / p>

我想要讨论的主要内容是我的GetProperty函数本身。有没有更好的方法来解决这个问题,还是我已经在正确的轨道上了?任何进一步的空检查或我应该做的事情?

2 个答案:

答案 0 :(得分:2)

仅仅因为问题被标记为 C#-7.0 ,我想提供 C#-7.0 功能的答案:

public static PropertyInfo GetProperty<TObject, TProperty>(
  this Expression<Func<TObject, TProperty>> selectorExpression)
    => selectorExpression.Body is MemberExpression memberExpression
      && memberExpression.Member is PropertyInfo propertyInfo
        ? propertyInfo
        : throw new InvalidCastException();

答案 1 :(得分:1)

这对我有用:

public static PropertyInfo GetProperty<T>(this Expression<Func<T, decimal>> selectorExpression)
{
    var memberExpression = selectorExpression.Body as MemberExpression;
    if (memberExpression == null) throw new InvalidCastException();
    return memberExpression.Member as PropertyInfo;
}

然后,使用此代码,我将42写入控制台:

void Main()
{
    Expression<Func<Foo, decimal>> exp = q => q.Bar;
    var p = exp.GetProperty();

    var f = new Foo();
    p.SetValue(f, 42m);
    Console.WriteLine(f.Bar);
}

public class Foo
{
    public decimal Bar { get; set; }
}