Wojciech Szabowicz
Wojciech Szabowicz

Reputation: 4198

Group list of generic objects by its property

I have a question, I am trying to group a list of generic objects by certain key property that is inside those objects like:

    public void GroupChanges<TResult>(List<TResult> changes)
    {
        const string KeyPropertyName = "TransactionSequence";

        List<IGrouping<byte[], TResult>> changeSet = changes
            .GroupBy(change => /*change.TransactionSequence */ <- property avaible in every object that is 
                change.GetType().GetProperty(KeyPropertyName).GetValue(change)
                , new ArrayComparer<byte>())
            .ToList();
    }

Model of data and models is fairly simple I've got one abstract generic model above all other that contains Key property, models inherit that property and data is filled from Db and data structure is just a generic list of those models.

Now if I strongly type model its OK, how this can be changed?

Upvotes: 1

Views: 716

Answers (2)

Jodrell
Jodrell

Reputation: 35716

Okay, if your function is generic, how does it know if TResult will have a "TransactionSequence" property? It cannot know this and be generic. Unless you put a constraint on the type, see Titian's answer, this makes the function less generic but that could be useful.

You'd need to ask for a delegate like Func<TResult, TProperty> but then you might as well just call GroupBy directly.

Upvotes: 2

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249606

You need to declare an interface that is implemented by all the types you will pass to the method. And add it as a type constraint to your method. The you can access properties of the interface.

    interface ICommon
    {
        byte[] TransactionSequence { get; set; }
    }
    public void GroupChanges<TResult>(List<TResult> changes) 
         where TResult: ICommon 
    {
        List<IGrouping<byte[], TResult>> changeSet = changes
                .GroupBy(change => change.TransactionSequence , new ArrayComparer<byte>())
                .ToList();
    }

Note: The type constraint will also work an abstract/base class. This will not work if you LINQ over an IQueryable with EF

Upvotes: 3

Related Questions