根据属性名称数组创建对象的子集

jho*_*nly 6 .net c# linq reflection

我有一个类和一组属性名称定义如下:

public class Dog {
    public string Name { get; set; }
    public string Breed { get; set; }
    public int Age { get; set; }
}

var desiredProperties = new [] {"Name", "Breed"};
Run Code Online (Sandbox Code Playgroud)

我还有一个返回dog对象列表的方法:

List<Dog> dogs = GetAllDogs();
Run Code Online (Sandbox Code Playgroud)

有没有办法可以返回dogs只包含desiredProperties数组中定义的属性的子集?最终,此结果列表将序列化为JSON.

考虑到允许用户指定任何属性组合(假设它们都是有效的)作为数组中的输出,我一直在努力解决这个问题.更多例子:

var desiredProperties = new [] {"Name", "Age"};
// Sample output, when serialized to JSON:
// [
//   { Name: "Max", Age: 5 },
//   { Name: "Spot", Age: 2 }
// ]

var desiredProperties = new [] {"Breed", "Age"};
// [
//   { Breed: "Scottish Terrier", Age: 5 },
//   { Breed: "Cairn Terrier", Age: 2 }
// ]
Run Code Online (Sandbox Code Playgroud)

Ham*_*jam 5

您可以编写一个函数来做到这一点。使用下面的扩展方法。

public static class Extensions
{
    public static object GetPropertyValue(this object obj, string propertyName)
    {
        return obj.GetType().GetProperty(propertyName).GetValue(obj);
    }

    public static List<Dictionary<string, object>> FilterProperties<T>(this IEnumerable<T> input, IEnumerable<string> properties)
    {
        return input.Select(x =>
        {
            var d = new Dictionary<string, object>();
            foreach (var p in properties)
            {
                d[p] = x.GetPropertyValue(p);
            }
            return d;
        }).ToList();
    }
}
Run Code Online (Sandbox Code Playgroud)

像测试

var dogs = GetAllDogs();

var f1 = dogs.FilterProperties(new[]
{
    "Name", "Age"
});

var f2 = dogs.FilterProperties(new[]
{
    "Breed", "Age"
});

Console.WriteLine(JsonConvert.SerializeObject(f1));
Console.WriteLine(JsonConvert.SerializeObject(f2));
Run Code Online (Sandbox Code Playgroud)

结果是

[{“ Name”:“ Spot”,“ Age”:2},{“ Name”:“ Max”,“ Age”:5}]
[{“ Breed”:“ Cairn Terrier”,“ Age”:2} ,{“品种”:“苏格兰梗”,“年龄”:5}]