Filter anonymous object list by executing string clause in where condition

1.5k Views Asked by At

DOTNETFIDDLE

I have create a anonymous object list like below.....

List < Object > _dynamicObjectList = new List < Object > ();
for (int i = 0; i < 5; i++) {
    _dynamicObjectList.Add(new {
        ID = i, Name = "stu" + i, Address = "address234324" + i, DateField = DateTime.Now.AddDays(i)
    });
}

Now I need to create string query. My string query is given below..

string searchStr ="it.ID= 1 || it.ID= 2 || it.Name= "stu1" || it.Name= "stu2"";

In the last step I am going to filter my list with the above string...

var returnList= _dynamicObjectList.GetFilteredData(searchStr );

The method which executes Dynamic object is given below...

public static IQueryable GetFilteredData < T > (this IEnumerable < T > source, string searchCriteria) {

    if (!string.IsNullOrEmpty(searchCriteria)) {
        IList < T > returnList = new List < T > ();
        returnList = source.AsQueryable().Where(searchCriteria).ToList();
        return returnList.AsQueryable();
    } else {
        return source.AsQueryable();
    }

}

During execution system provide an error

No property or field 'ID' exists in type 'Object'

2

There are 2 best solutions below

2
On

An easy way to initialize your list is using Enumerable.Range and anonymous type:

var list = Enumerable.Range(0,5).Select(i => new {
    ID = i, 
    Name = "stu" + i, 
    Address = "address234324" + i, 
    DateField = DateTime.Now.AddDays(i)
});

Regardless of the way you initialize it, I see two major problems with your GetFilteredData method though:

  1. You cannot pass your anonymous type to a generic function. You would need to cast it to a IEnumeration<object> or use dynamic type, which totally defeats the purpose of your anonymous type.
  2. You need to parse text in searchCriteria to a some sort list of criteria, before it can be applied to your collection. Depending on the allowed syntax, it could be a simple or not so simple task. When you get the parser, then you you'll need write an extension .Where method which accepts string as criteria.

You'll make your life easier if you define a regular type for your collection and clarify what the filtering criteria should be. Based on your example they could two simple lists - one for IDs, and another one for Names. Then you can parse your string into those two collections and then use those collection to filter your original list.

2
On

<T> is Object because you're passing in a List<Object>, and an Object doesn't have the properties on it you're looking for.

If your _dynamicObjectList is declared as a list of those anonymous types then the query can be executed fine, for example if you declare _dynamicObjectList as:

var _dynamicObjectList = new[] {
            new {ID = 0, Name = "stu" + 0, Address = "address234324" + 0, DateField = DateTime.Now.AddDays(0)},
            new {ID = 1, Name = "stu" + 1, Address = "address234324" + 1, DateField = DateTime.Now.AddDays(1)},
            new {ID = 2, Name = "stu" + 2, Address = "address234324" + 2, DateField = DateTime.Now.AddDays(2)},
            new {ID = 3, Name = "stu" + 3, Address = "address234324" + 3, DateField = DateTime.Now.AddDays(3)},
            new {ID = 4, Name = "stu" + 4, Address = "address234324" + 4, DateField = DateTime.Now.AddDays(4)},
        }.ToList();

More info: A generic list of anonymous class

I think your best bet, if possible, would be to avoid using an anonymous type and just create a class to hold your data.