TL; DR
orderby typeof(T).Equals(mi.DeclaringType) ? 1 : -1
будет сначала толкать базовый memberInfo и сохранять порядок, определенный в классе.
Полный ответ:
для достижения той же целии используя DeclaringType, как предлагалось ранее, я определил следующий метод:
public static IEnumerable<MemberInfo> GetAllFieldsAndPropertiesOfClass<T>()
{
return
from mi in typeof(T).GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
let ignoreAttr = (IgnoreSerializationAttribute)Attribute.GetCustomAttribute(mi, typeof(IgnoreSerializationAttribute))
where (mi.MemberType == MemberTypes.Field || mi.MemberType == MemberTypes.Property)
&& (ignoreAttr == null || ignoreAttr != null && !ignoreAttr.Ignore)
orderby typeof(T).Equals(mi.DeclaringType) ? 1 : -1
select mi;
}
В этом методе я также определил пользовательский атрибут, который явно игнорирует некоторые свойства из сериализации:
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class IgnoreSerializationAttribute : Attribute
{
public bool Ignore { get; private set; }
public IgnoreSerializationAttribute(bool ignore)
{
Ignore = ignore;
}
}
Также можно добавить другой пользовательский атрибут для определения порядка, например
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class ColumnOrderAttribute : Attribute
{
public int Order { get; private set; }
public ColumnOrderAttribute(int order)
{
Order = order;
}
}
, используемый следующим образом:
public static IEnumerable<MemberInfo> GetAllFieldsAndPropertiesOfClassOrdered<T>()
{
return
from mi in GetAllFieldsAndPropertiesOfClass<T>()
let orderAttr = (ColumnOrderAttribute)Attribute.GetCustomAttribute(mi, typeof(ColumnOrderAttribute))
orderby orderAttr == null ? int.MaxValue : orderAttr.Order, mi.Name
select mi;
}
Я использую эти методы для сериализации списка объектовиспользование других объектов в файлах CSV ...