如何在.net中使用c#选择类型化对象列表中对象's属性的所有值

本文关键字:对象 属性 列表 net 类型化 选择 | 更新日期: 2023-09-27 18:08:29

啊,我该怎么解释这个…可能是一个简单的问题,但我脑子很乱。

假设我有这样一个类:

public class NestedObject
{
    public string NestedName { get; set; }
    public int NestedIntValue { get; set; }
    public decimal NestedDecimalValue { get; set; }
}
public class SomeBigExternalDTO
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public int SomeIntValue { get; set; }
    public long SomeLongValue { get; set; }
    public decimal SomeDecimalValue { get; set; }
    public string SomeStringValue { get; set; }
    public NestedObject SomeNestedObject { get; set; }
    // ... thousands more of these properties... inherited code
}

我要填充的类在这里:

public class MyResult
{
    public int UserId { get; set; }  // user id from above object
    public string ResultValue { get; set; }  // one of the value fields from above with .ToString() executed on it
}

我想做的是创建一个帮助器来返回这个对象列表中所有实例的属性值(我想横截面是我可以描述它的最好方式):

var foo = new List<SomeBigExternalDTO>();
foo = GetMyListOfSomeBigExternalDTO();
public static List<MyResult> AwesomeHelper(List<SomeBigExternalDTO> input, SearchableProperty thePropertyIWant)
{
    // some magic needs to happen here...
}
这里棘手的部分是我想动态地传递基于链接选择器的属性(我不知道如何做到这一点):
var output = AwesomeHelper(GetMyListOfSomeBigExternalDTO(), x => x.SomeIntValue);
var output2 = AwesomeHelper(GetMyListOfSomeBigExternalDTO(), x => x.SomeNestedObject.NestedIntValue); 

这应该返回一个MyResult对象列表,其中包含UserId和SomeIntValue.ToString(),对应于输入列表中的每个项目。

哇,我真的希望这是有意义的。如果不清楚,请告诉我,我会提供更多细节。我真的希望这是一些被我忽略的东西。

你知道我该怎么做吗?

如何在.net中使用c#选择类型化对象列表中对象's属性的所有值

可以实现它作为一个扩展方法:

public static IEnumerable<MyResult> AwesomeHelper(this IEnumerable<SomeBigExternalDTO> input, 
                                                  Func<SomeBigExternalDTO, int> intMapper)
{
    foreach (var item in input)
        yield return new MyResult() 
        {
            UserId = item.UserId, 
            ResultValue = intMapper(item) 
        };
}

现在你可以这样使用:

var output = GetMyListOfSomeBigExternalDTO().AwesomeHelper( x => x.SomeIntValue);
var output2 = GetMyListOfSomeBigExternalDTO().AwesomeHelper( x => x.SomeNestedObject.NestedIntValue); 

已经说过-不要这样做-它看起来像是你在重新发明Linq已经提供给你的东西,你可以只使用Linq:

var output = GetMyListOfSomeBigExternalDTO().Select( x=> new MyResult()
             {
                UserId = item.UserId, 
                ResultValue = x.SomeIntValue
             });
var output2 = GetMyListOfSomeBigExternalDTO().Select( x=> new MyResult()
             {
                UserId = item.UserId, 
                ResultValue = x.SomeNestedObject.NestedIntValue
             });

通常当你试图创建一个通用的列表操作符时,你最终会重新实现LINQ已经提供给你的东西。

下面是你需要的LINQ代码(没有AwesomeHelper函数):

var results = list.Select(l => new MyResult()
{
    UserId = l.UserId,
    ResultValue = l.SomeDecimalValue.ToString()
}).ToList();

相当简单。

如果你想有一个AwesomeHelper函数,如你所要求的,那么它看起来像这样:

public static List<MyResult> AwesomeHelper(
    List<SomeBigExternalDTO> input,
    Func<SomeBigExternalDTO, object> selector)
{
    return input
        .Select(i => new MyResult()
        {
            UserId = i.UserId,
            ResultValue = selector(i).ToString()
        })
        .ToList();
}

调用代码看起来像这样:

var results = AwesomeHelper(list, x => x.SomeIntValue);

对我来说,现在比LINQ选项的可读性更低。现在有一些魔法正在被创造出来,很难弄清楚是什么。

我有一个可以让你两全其美的选择。

首先,定义一个名为ToMyResult的扩展方法,使用字段选择器将单个SomeBigExternalDTO实例映射到单个MyResult,如下所示:

public static class AwesomeHelperEx
{
    public static MyResult ToMyResult(
            this SomeBigExternalDTO input,
            Func<SomeBigExternalDTO, object> selector)
    {
        return new MyResult()
        {
            UserId = input.UserId,
            ResultValue = selector(input).ToString()
        };
    }
}

现在调用代码清晰、灵活、简洁。

var results = (
        from item in list
        select item.ToMyResult(x => x.SomeLongValue)
    ).ToList();