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

时间:2017-09-14 22:57:55

标签: c# json linq dynamic

我的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
    }
] 

2 个答案:

答案 0 :(得分:2)

您可以使用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解决方案。 :)

答案 1 :(得分: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本身进行断言。