繁体   English   中英

C#,如何从动态对象的字符串参数传递属性名称

[英]C#, How to pass property name from string parameter for Dynamic object

我的API响应将返回JSON对象的列表,我需要验证列表的顺序,因此我编写了如下函数。 但是我对LINQ按句排序有一个问题,它仅在指定实际字段时才有效,但是我需要将此字段名称作为参数传递。 所以像var expectedList = jObjList.OrderBy(x => x.parameterFieldName.ToString()); 请给我一些建议,非常感谢。

public void VerifyOrderBy(string jsonString, string parameterFieldName)
{
    List<dynamic> jObjList = JsonConvert.DeserializeObject<List<dynamic>>(jsonString);
    var expectedList = jObjList.OrderBy(x => x.LastName.ToString());
    Assert.IsTrue(expectedList.SequenceEqual(jObjList));
}

JSON字符串如下所示

[
    {
        "FirstName": "w3pCj",
        "LastName": "mSJOV",
        "IsDeleted": false
    },
    {
        "FirstName": "rMnH7",
        "LastName": "rMnH7",
        "IsDeleted": false
    },
    {
        "FirstName": "Jia",
        "LastName": "Yu",
        "IsDeleted": false
    }
] 

您可以像这样使用nameof()运算符关键字:

jObjList.OrderBy(x => nameof(x.LastName));

更新#1

假设我们有一个Person类:

public class Person
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public bool IsDeleted { get; set; }
}

假设我们有一个人员列表:

var people =
    JsonConvert
        .DeserializeObject<List<Person>>(
            File.ReadAllText("data.json", Encoding.UTF8)
        );

我们可以有一个包含将要按以下顺序排序的属性名称的参数:

string parameterName = nameof(Person.LastName); // or simply "LastName"

我们得到对该属性的引用:

PropertyInfo orderByProperty =
    typeof(Person)
        .GetProperties()
        .SingleOrDefault(property => property.Name == parameterName);

现在我们可以按选定的属性排序:

var result = people.OrderBy(person => orderByProperty.GetValue(person)).ToList();

请注意:

  • 当然,您应该检查orderByProperty是否不为null :)
  • 这仅适用于内存中对象(LINQ-to-Objects),而不适用于数据库集(LINQ-to-SQL,EF)

不要忘记添加所需的using语句才能获得PropertyInfo

using System.Reflection;

更新#2

如果您具有如此简单的json结构,并且想使用dynamic对象进行排序,则可以这样实现:

var people =
    JsonConvert
        .DeserializeObject<List<dynamic>>(
            File.ReadAllText("data.json", Encoding.UTF8)
        );

string parameterName = "LastName";

var result =
    people
        .OrderBy(person =>
        {
            var personObject = person as JObject;
            var propertyValueObject = personObject.GetValue(parameterName) as JValue;

            return propertyValueObject.Value;
        })
        .ToList();

虽然可以,但是我更喜欢UPDATE#1解决方案。 :)

这是使用自定义比较器的实现。 这使您可以传递任何属性名称:

public class JObjComp<T> : IComparer<T>
{
    private string _field;

    public JObjComp(string field)
    {
        _field = field;
    }

    int IComparer<T>.Compare(T a, T b)
    {
        //this is bit flimsy but as we know that passed object is 
        //a dynamic, should work
        dynamic aa=(dynamic)a;
        dynamic bb=(dynamic)b;
        return string.Compare(aa[_field].ToString(), bb[_field].ToString());
    }
}

现在使用我们的自定义比较器:

List<dynamic> jObjList = JsonConvert.DeserializeObject<List<dynamic>>(jstr);
jObjList.Sort(new JObjComp<dynamic>(field));

该列表是就地排序的,因此您可以使用jObjList本身进行断言。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM