eYe
eYe

Reputation: 1733

Sort list of PropertyInfos by property value of its attribute

I have an Dto object of type:

public class ClassA
{       
    [DataMember(Order = 10)]
    public string Code { get; set; }

    [DataMember(Order = 20)]
    public string Symbology { get; set; }

    [DataMember(Order = 30)]
    public string Category { get; set; }

    public string NonMemberPropertyA { get; set; }
}

I am interested in obtaining all the DataMember decorated properties:

 var propertyInfos = type.GetProperties().Where(p => Attribute.IsDefined(p, typeof (DataMemberAttribute)));

Now I need to sort my propertyInfos based on the Orderproperty of the DataMember attribute. Because some might be out of order.

So I tried to add:

.OrderBy(p => ((DataFormat)Attribute.GetCustomAttribute(p, typeof (DataFormat))).Order);

But I get "cannot be inferred from usage" error.

Upvotes: 3

Views: 764

Answers (2)

GreatAndPowerfulOz
GreatAndPowerfulOz

Reputation: 1775

Do this:

var propertyInfos = type
            .GetProperties(BindingFlags.Public | BindingFlags.NonPublic)
            .Where(m => m.GetCustomAttributes(typeof(DataMemberAttribute), false).Length > 0)
            .SelectMany(m => m.GetCustomAttributes(false).OfType<DataMemberAttribute>())
            .OrderBy(m => m.Order)
            .ToArray();

Upvotes: 2

Ric
Ric

Reputation: 13248

Got it working using this:

var orders = a1
    .GetType()
    .GetProperties()
    .Where(x => Attribute.IsDefined(x, typeof(DataMemberAttribute)))
    .Select(x => new { Att = x.GetCustomAttribute<DataMemberAttribute>(true), Prop = x })
    .OrderBy(x => x.Att.Order);

The Select() projects an anonymous object comprising of the property itself and the attribute so that you can then order by the attribute.

a1 is an instance of your object ClassA

I modified your code and got it working:

var orders = a1
    .GetType()
    .GetProperties()
    .Where(p => Attribute.IsDefined(p, typeof(DataMemberAttribute)))
    .OrderBy(p => ((DataMemberAttribute)Attribute.GetCustomAttribute(p, typeof(DataMemberAttribute))).Order);

Upvotes: 3

Related Questions