【问题标题】:Is there a cleaner way to set Properties of Generic Classes?有没有更简洁的方法来设置泛型类的属性?
【发布时间】:2017-04-29 06:05:29
【问题描述】:

这是我目前所拥有的,它工作正常。我只是想知道是否有更顺畅的方法:

    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“权重”属性将 IEnumerable 中的值划分为选定的 setter 属性。

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

【问题讨论】:

  • 你为什么使用Expression 而不仅仅是一个普通的Func
  • 为什么还要将其限制为十进制属性?
  • 小数限制只是因为我在项目中使用它的所有时间都是小数,它是任意的。如何从 Func 获取属性?
  • myList.ForEach( e => e.Value = 100 )
  • @SirRufo 请阅读我的最后一段。

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


【解决方案1】:

仅仅因为这个问题被标记为 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();

【讨论】:

  • 哦,太好了,我没有意识到你可以在执行 is 语句时捕获到 var,超级漂亮!
【解决方案2】:

这对我有用:

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

【讨论】:

  • 哦,太好了,你可以直接投吗?这就是我要找的!我试试看。
猜你喜欢
  • 1970-01-01
  • 2018-10-28
  • 1970-01-01
  • 2012-11-10
  • 1970-01-01
  • 2015-12-14
  • 1970-01-01
  • 2023-02-24
  • 1970-01-01
相关资源
最近更新 更多