如何使用表达式为属性分配值?

时间:2018-08-23 14:12:04

标签: c# lambda

我有一堂课

public class Item { 
    public string Name { get; set; }
    public object Value { get; set; }
}

以及此类的集合:

ICollection<Item> items;

目前,我有以下内容:

var item = items.Where(x => x.Name == "id").FirstOrDefault();
if (item != null)
    item.Value = 1;

var item = items.Where(x => x.Name == "name").FirstOrDefault();
if (item != null)
    item.Value = "Username";

//etc... for a number of items

是否可以通过Expression和inline函数来实现上述目的,但是用更少且更简洁的代码来实现?

类似的东西:

items.Set(x => x.Name == "id", value = 1);
items.Set(x => x.Name == "name", value = "username");

4 个答案:

答案 0 :(得分:2)

您可以执行以下操作:

public static class Extensions
{
    public static void Set<T>(
        this ICollection<T> source, 
        Func<T, bool> predicate, 
        Action<T> action)
    {
        var item = source.FirstOrDefault(predicate);
        if(item != null)
        {
            action(item);
        }
    }
}

用法:

var collection = new List<User>()
{
    new User { Name = "Pavel", Id = 1 },
    new User { Name = "Anna", Id = 2}
};

collection.Set(q => q.Id == 1, w => w.Name = "Jacob");

答案 1 :(得分:1)

除了对您的班级进行一些补充外,您还可以这样:

items.FirstOrDefault(x => x.Name == "id")?.SetValue(1);

空条件运算符?.(又名Elvis运算符)可在调用SetValue(1)时保护您免受默认/空值的影响,但它不允许进行赋值,即您无法对其使用属性。

您的课程将需要SetValue方法:

public void SetValue(object arg)
{
    Value = arg;
}

答案 2 :(得分:0)

我可以想到使用.ToList().ForEach()的解决方案,但这不是很可读。

using System;
using System.Linq;
using System.Collections.Generic;

public class Item { 
    public string Name { get; set; }
    public object Value { get; set; }
}

public class Program
{
    public static void Main()
    {
        var items = new List<Item>();
        items.Add(new Item(){
            Name = "test",
            Value = 2
        });
        items.Add(new Item(){
            Name = "id",
            Value = 0
        });

        items.Where(i => i.Name == "id").ToList().ForEach(i => i.Value = 1);
        Console.WriteLine(items[1].Name + " : " + items[1].Value);
    }
}

链接到小提琴:https://ideone.com/7m66rg

答案 3 :(得分:0)

您的语法items.Set(x => x.Name == "id", value = 1);无效。但是,如果使用以下命令,则可以使用items.Set(x => x.Name == "id", value : 1);items.Set(x => x.Name == "id", 1);

public static class ItemExtensions
{

    public static void Set(this ICollection<Item> items, Func<Item, bool> predicate, object value)
    {
        var item = items.FirstOrDefault(predicate);
        if (item != null)
            item.Value = value;
    }

}

说明

  1. 您正在寻找现有类ICollection的函数。因此,您将需要创建扩展功能。
  2. 您正在尝试将某些内容传递给Linq Where函数。检查传递到where的确切数据类型。您会注意到它的Func<TSource, bool> predicate。在这种情况下,我们知道TSourceItem
  3. 您也可以直接在FirstOrDefault内部使用该谓词