How to get a list of property names in a class in a specific order

I have a class similar to:

public class MyClass : MyBaseClass
{
        public string Field1 { get; set; }
        public string Field2 { get; set; }
        public string Field3 { get; set; }
        public string Field4 { get; set; }
}

public class MyBaseClass
{
        public string BaseField1 { get; set; }
        public string BaseField2 { get; set; }
        public string BaseField3 { get; set; }
        public string BaseField4 { get; set; }
}

Then I created a method for pulling names from a class.

private void MyMethod<T>(List<T> listData) where T : class
{
    String[] fieldNames = Array.ConvertAll<PropertyInfo, String>(typeof(T).GetProperties(), delegate(PropertyInfo fo) { return fo.Name; });

    // Do something with the fieldNames array....
}

Therefore, when I get my array, it will be in the following order:

Field1
Field2
Field3
Field4
BaseField1
BaseField2
BaseField3
BaseField4

I was interested to know if it was possible to change the order so that the fields of the base class are first accompanied by the fields of the derived class?

+6
source share
3 answers

Let me implement a simple method to get how deep a class is in the class hierarchy.

null <- object <- ... <- MyBaseClass <- MyClass <- ...

Implementation

// 0     - null
// 1     - object
// ...
// n     - MyBaseClass
// n + 1 - MyClass
// ...
private static int TypeLevel(Type type) {
  if (null == type)
    return 0;

  return TypeLevel(type.BaseType) + 1;
}

And then using Linq sorting by this criterion, the only little trick is to use DeclaringType- where (in which class) the property was declared:

// fieldNames are actually properties' names
string[] fieldNames = typeof(MyClass)
  .GetProperties()
  .OrderBy(p => TypeLevel(p.DeclaringType)) // <- base first, derived last
  .ThenBy(p => p.Name) // <- let organize properties within each class
  .Select(p => p.Name) 
  .ToArray();

Console.Write(string.Join(Environment.NewLine, fieldNames));

Result:

BaseField1
BaseField2
BaseField3
BaseField4
Field1
Field2
Field3
Field4

Finally, your method might be something like this:

// we don't want any restictions like "where T : class"
private void MyMethod<T>(List<T> listData) {
  ...
  string[] fieldNames = typeof(T)
    .GetProperties()
    .OrderBy(p => TypeLevel(p.DeclaringType)) // <- base first, derived last
    .ThenBy(p => p.Name) // <- let organize properties within each class
    .Select(p => p.Name)
    .ToArray();

  ...
}
+5

, , ,

static void GetProperties(Type type, List<string> returnValue) {
    var props = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
    returnValue.AddRange(props.Select(p => p.Name).OrderBy(p => p));
}

private void MyMethod<T>(List<T> listData) where T : class {
    var type = typeof(T);
    List<string> properties = new List<string>();
    while (type != null) {
        GetProperties(type, properties);
        type = type.BaseType;
    }
}
0

Select all properties of the base class and combine with all the properties of the derived class. Distinct () will remove all duplicates. If you need a more difficult task, you will have to try @Vikhram's solution.

        var properties = typeof(MyBaseClass).GetProperties().Select(x => x.Name)
            .Union(typeof(MyClass).GetProperties().Select(x => x.Name)).Distinct();
-1
source

Source: https://habr.com/ru/post/1017137/


All Articles