Get properties in order of declaration using reflection
On .net 4.5 (and even .net 4.0 in vs2012) you can do much better with reflection using clever trick with [CallerLineNumber]
attribute, letting compiler insert order into your properties for you:
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public sealed class OrderAttribute : Attribute
{
private readonly int order_;
public OrderAttribute([CallerLineNumber]int order = 0)
{
order_ = order;
}
public int Order { get { return order_; } }
}
public class Test
{
//This sets order_ field to current line number
[Order]
public int Property2 { get; set; }
//This sets order_ field to current line number
[Order]
public int Property1 { get; set; }
}
And then use reflection:
var properties = from property in typeof(Test).GetProperties()
where Attribute.IsDefined(property, typeof(OrderAttribute))
orderby ((OrderAttribute)property
.GetCustomAttributes(typeof(OrderAttribute), false)
.Single()).Order
select property;
foreach (var property in properties)
{
//
}
If you have to deal with partial classes, you can additionaly sort the properties using [CallerFilePath]
.
Get properties of class by order using reflection
You are missing brackets ()
on FirstOrDefault
operator. Also you should deal with case when default value is returned. I suggest to select Order
value before getting first or default value. That will return 0
for all properties which don't have DisplayAttribute
:
var prop = typeof(A)
.GetProperties()
.OrderBy(p => p.GetCustomAttributes(typeof(DisplayAttribute), true)
.Cast<DisplayAttribute>()
.Select(a => a.Order)
.FirstOrDefault());
If you want properties without DisplayAttribute to be last, you can provide Int32.MaxValue
as default value to be returned:
.Select(a => a.Order)
.DefaultIfEmpty(Int32.MaxValue)
.First()
`Type.GetProperties` property order
The order simply isn't guaranteed; whatever happens.... Happens.
Obvious cases where it could change:
- anything that implements ICustomTypeDescriptor
- anything with a TypeDescriptionProvider
But a more subtle case: partial classes. If a class is split over multiple files, the order of their usage is not defined at all. See Is the "textual order" across partial classes formally defined?
Of course, it isn't defined even for a single (non-partial) definition ;p
But imagine
File 1
partial class Foo {
public int A {get;set;}
}
File 2
partial class Foo {
public int B {get;set:}
}
There is no formal declaration order here between A and B. See the linked post to see how it tends to happen, though.
Re your edit; the best approach there is to specify the marshal info separately; a common approach would be to use a custom attribute that takes a numeric order, and decorate the members with that. You can then order based on this number. protobuf-net does something very similar, and frankly I'd suggest using an existing serialization library here:
[ProtoMember(n)]
public int Foo {get;set;}
Where "n" is an integer. In the case of protobuf-net specifically, there is also an API to specify these numbers separately, which is useful when the type is not under your direct control.
C# Reflection property order
The fields in a type are not "ordered". The ordering of the items in those methods is an implementation detail and relying on them is strongly discouraged.
You should order the items yourself, with the expectation that they could start at any position, to ensure your program is robust instead of fragile.
Since each property can be asked for the type that declares it you can create a lookup at the start that gives a number to each class in the hierarchy from the type you start with all the way up to object
by walking the BaseType
property of Type
and order by the lookup value of the declaring type of each property:
public static IEnumerable<PropertyInfo> GetOrderedProperties(Type type)
{
Dictionary<Type, int> lookup = new Dictionary<Type, int>();
int count = 0;
lookup[type] = count++;
Type parent = type.BaseType;
while (parent != null)
{
lookup[parent] = count;
count++;
parent = parent.BaseType;
}
return type.GetProperties()
.OrderByDescending(prop => lookup[prop.DeclaringType]);
}
Get attributes in order of declaration using reflection
The C# language specification says in 17.2 Attribute specification:
The order in which attributes are specified in such a list, and the order in which sections attached to the same program entity are arranged, is not significant.
For instance, the attribute specifications
[A][B]
,[B][A]
,[A, B]
, and[B, A]
are equivalent.
So the compiler can re-order them as it wants, and the methods for retrieving attributes can't guarantee to return them in any order.
You can of course use the workaround proposed in the question you link to, using [CallerLineNumber]
.
How to get class properties in order of declaration when serialize
Properties are not guaranteed to have or maintain any specific order in JavaScript. What you will do in your C# code can't change this "limitation".
BTW, the same goes for .net.
Get properties from class object using reflection where property should be public and having get or get and set both
You should not be using the bitwise AND (&
), but the bitwise OR (|
):
var properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty);
Kotlin get property in the same order they are declared
Easier way would be to read properties from the constructor:
ClassWithSortedProperties::class.
primaryConstructor?.
parameters?.
forEachIndexed { i, property ->
println("$i $property")
}
Related Topics
Parsing HTML Page with HTMLagilitypack
Can Itextsharp.Xmlworker Render Embedded Images
Why Always Close Database Connection
How to Hide a Process in Task Manager in C#
Use of Null Check in Event Handler
C# Error: Parent Does Not Contain a Constructor That Takes 0 Arguments
C#: List All Classes in Assembly
Entity Framework Core 2.0.1 Eager Loading on All Nested Related Entities
What Are Independent Associations and Foreign Key Associations
Evaluate String with Math Operators
Read the Value of an Attribute of a Method
What Characters Are Allowed in C# Class Name