Home > database >  Is it possible to pull out a list of particular field values from a collection of generic objects in
Is it possible to pull out a list of particular field values from a collection of generic objects in

Time:02-07

I have the following method in a class I am using for pagination in my app:

public static PagedList<T> ToPagedList(IEnumerable<T> source, int pageNumber, int pageSize)
        {
            var count = source.Count();
            var items = source
              .Skip((pageNumber - 1) * pageSize)
              .Take(pageSize).ToList();

            return new PagedList<T>(items, count, pageNumber, pageSize);
        }

In this method I am passing in a collection of generic objects as IEnumerable<T> source which regardless of type will always have an Id field. What I'd like to do is pull out all of the Ids for these objects and store them in a list to be passed into my PagedList constructor. Is this possible?

CodePudding user response:

the best way would be create an interface

public interface IBaseClass{
  public int Id {get; set;}
}

in this case you could change method header

static PagedList<T> ToPagedList<T>(IEnumerable<T> source, int pageNumber, int pageSize) 
                    where T : IBaseClass

and ids

var ids=items.Select(i => i.Id ).ToList();

CodePudding user response:

Yes it is possible. You can use Reflection to get the value of a property.

item.GetType().GetProperty("Id").GetValue(item, null);

Edit: Respond to @CoolBots' comment

In case Id is a field, you can use GetField instead of GetProperty

item.GetType().GetField("Id").GetValue(item, null);

but if the item doesn't have the "Id" property, this code will fail, so remember to check for null.

CodePudding user response:

An interface would be the best way, but you specifically said "field" and interfaces cannot contain fields.

You could get around this limitation with an abstract base class, but you cannot have multiple base classes on a single class (if applicable).

...All of this assumes that you have the ability to modify those classes.

Another way to do this would be:

public static PagedList<T> ToPagedList<T>(IEnumerable<T> source, int pageNumber, int pageSize)
{
    var count = source.Count();

    var items = source
        .Skip((pageNumber - 1) * pageSize)
        .Take(pageSize).ToList();

    var ids = items
        .Select(i => ((dynamic)i).Id)   // field is **always** named "Id"
        .Cast<int>()                    // its type is **always** int
        .ToList();
            
    return new PagedList<T>(items, count, pageNumber, pageSize/*, ids*/); // pass ids
}

This assumes the field in question is named "Id", and it is an int.

Adjust accordingly and handle potential errors.

I think I originally misunderstood the question, the comment by @Dusan caused me to reevaluate and update the code.

  •  Tags:  
  • Related