lizziv
lizziv

Reputation: 193

Use Custom Attribute to sort FieldList

I want to retrieve the fields in my object in a particular order. I found a way to use reflection to retrieve the fields, but the fields are not guaranteed to be returned in the same order each time. Here is the code I am using to retrieve the fields:

ReleaseNote rn = new ReleaseNote();
Type type = rn.GetType();
FieldInfo[] fi = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);

I found this answer to another question, which explains how to add a custom attribute and use it to sort the fields. Based on this, I believe I need to update my code to retrieve the fields in sorted order by creating a custom attribute, "MyOrderAttribute" which I will use to sort the FieldInfo array.

Here I created the attribute and added it to my fields:

namespace TestReleaseNotes
{
    [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
    public class MyOrderAttribute : Attribute
    {
        public MyOrderAttribute(int position)
        {
            this.Position = position;
        }

        public int Position { get; private set; }
    }

    class ReleaseNote
    {
        [MyOrder(0)]
        private string title;
        [MyOrder(1)]
        private string status;
        [MyOrder(3)]
        private string implementer;
        [MyOrder(3)]
        private string dateImplemented;
        [MyOrder(4)]
        private string description;

And here I try to use the attribute to sort the field list:

ReleaseNote rn = new ReleaseNote();
Type type = rn.GetType();
FieldInfo[] fi = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic).OrderBy(f => f.Position);

This gives me the error "'FieldInfo does not contain a definition for 'Position' and no accessible extension method 'Position' accepting a first argument of type 'FieldInfo' could be found (are you missing a using directive or an assembly reference?)"

I also tried the GetCustomAttribute method, which yields the error "'MyOrderAttribute' is a type, which is not valid in the given context":

FieldInfo[] fi = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic).OrderBy(f => f.GetCustomAttribute(MyOrderAttribute);

What is the correct syntax to access MyOrderAttribute and use it to sort my fields?

Upvotes: 3

Views: 286

Answers (1)

Max
Max

Reputation: 771

Use the following expression:

FieldInfo[] fi = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic).OrderBy(f => (int?)(f.CustomAttributes.Where(a=>a.AttributeType==typeof(MyOrderAttribute)).FirstOrDefault()?.ConstructorArguments[0].Value) ?? -1).ToArray();

the ?. and ?? operators are here to deal with fields without ordering attribute. It defaults non-ordered fields in -1 (i.e. in the beginning of the ordered list). Replace it with int.MaxValue, or 9999 to put unordered fields to the end.

Upvotes: 1

Related Questions