【问题标题】:How to change property for all items in list using expressions如何使用表达式更改列表中所有项目的属性
【发布时间】:2021-04-30 15:09:13
【问题描述】:

我需要实现以下功能:

List<T> Set<T, TV>(
    List<T> items, Expression<Func<T, TV>> extract, Expression<Func<T, TV>> update);

所以它会像这样工作:

List<Item> listOfModifiedItems =
    d.Set(listOfItems, i => i.SomeBooleanProperty, s => false );

因此,我们将 listOfModifiedItems 将所有项目的 SomeBooleanProperty 更改为 false。 我只是不明白如何正确地做到这一点。

【问题讨论】:

  • 这种功能的目的是什么?看起来像d.ForEach(t =&gt; t.SomeBooleanProperty = false) 没有涉及任何表达式树。
  • @SvyatoslavDanyliv 我们正在尝试为 Linq2Db 实现包装器,以便我们能够编写单元测试
  • 作为 linq2db 的创建者之一,我很惊讶没有这样的标签。模拟这种情况可能是一个挑战,那么为什么不使用内存中的 SQLite 来“模拟”数据库呢?
  • @SvyatoslavDanyliv 因为我从未想过!谢谢!!!
  • @SvyatoslavDanyliv 你手头有任何代码示例或任何其他示例吗?

标签: c# linq lambda


【解决方案1】:

如果有人正在寻找原始问题的答案:

public static List<T> Set<T, TV>(List<T> items, Expression<Func<T, TV>> extract, Expression<Func<T, TV>> update)
{
    // If the expression extract isn't member access
    if (extract.Body.NodeType != ExpressionType.MemberAccess)
        throw new InvalidOperationException();
    var memberAccess = (MemberExpression)extract.Body;

    // If the member access don't target a property
    if(memberAccess.Member.MemberType != System.Reflection.MemberTypes.Property)
        throw new InvalidOperationException();
    var propertyInfo = (System.Reflection.PropertyInfo)memberAccess.Member;

    // If the property don't have a setter to be updated
    if(!propertyInfo.CanWrite)
        throw new InvalidOperationException();

    var compiledUpdate = update.Compile();

    foreach (var item in items)
    {
        propertyInfo.SetValue(item, compiledUpdate.DynamicInvoke(item));
    }
    return items;
}

这仅管理问题的情况。如果你想管理更多的边缘情况,你将需要一些适应。表达式非常强大,但也很复杂。

【讨论】:

    猜你喜欢
    • 2020-03-25
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多