views:

460

answers:

2

I need to filter a generic List with data from a Json object. I have the deserialized object in a list with {name:'', value:''}. I need to search a data contract (which is also a list) with name as the field to search, and value as the value of the field. How do I accomplish these as they are generic. Here is the method:

public List<StaffingPositionsDataContract> GetStaffingPosition(string searchFilters)
{
    List<serializedForm> deserializedObject = JsonConvert.DeserializeObject<List<serializedForm>>(searchFilters);
    List<StaffingPositionsDataContract> staffingPositionResponse = new StaffingPositionsDataContract().LoadMockData();

    deserializedObject.ForEach(delegate(serializedForm filter) {


       });

    return staffingPositionResponse;
}

I wanted to try something simple as this:

var query = staffingPositionResponse .Where(filter.name + ".Contains(@0)", filter.value);

But Where does not except 2 arguments. Thanks in advance!

A: 

Why not use something like

List<SerializedForm >.FindAll( delegate(SerializedForm filter)
{
   return filter.name.IndexOf(filter.value) != -1;
});
Peter
oops that should be deserializedObject.FindAll
Peter
That looks good, but how do I tie that to my other list. Or how do I filter my data contract list with those values?
Zacho
The FindAll method is a filter method, it returns a new list with a subset of the items in the first list.So if you are wanting to filter your staffingPositionResponse you would call List<StaffingPositionsDataContract> filteredList = staffingPositionResponse.FindAll(delegate(StaffingPositionsDataContract position){ return DoesContractMeetFilter(deserializedObject, position);});
Peter
private bool DoesContractMeetFilter(List<serializedForm> filters, StaffingPositionsDataContract position){ return filters.FindAll(delegate(serializedForm filter){ return position.name.IndexOf(filter.value) != -1;}).Count > 0;}
Peter
Yes I see what you are doing, however position does not contain a definition for name, filter does. So if I switch position.name to filter.name, it doesn't filter anything. The problem is StaffingPositionsDataContract has 7 DataMembers to filter on, but the json object doesn't match. Thats why this is so difficult, but with the anwser, would be a really nice piece of code.
Zacho
ok so instead of just filtering on the name use a chained conditional statement likereturn position.Field1.IndexOf(filter.Value) != -1 || position.Field2.IndexOf(filter.Value) != -1 || position.Field3.IndexOf(filter.Value) != -1 || position.Field4.IndexOf(filter.Value) != -1 || position.Field5.IndexOf(filter.Value) != -1 || position.Field6.IndexOf(filter.Value) != -1 || position.Field7.IndexOf(filter.Value) != -1;Instead of return position.name.IndexOf(filter.value) != -1;
Peter
A: 

Thanks a million Peter! Here is what I ended up with to suit my needs:

   private bool DoesContractMeetFilter(List<SerializedForm> filters, StaffingPositionsDataContract position)
    {   
        return filters.FindAll(delegate(SerializedForm filter)
        {
            return string.Equals(position.PositionId.ToString(), filter.value) && 
                string.Equals(position.Series, filter.value) &&
                string.Equals(position.OrgLocation,filter.value) &&
                string.Equals(position.DutyStation, filter.value) &&
                string.Equals(position.BudgetStatus, filter.value)&&
                string.Equals(position.BudgetingEntity, filter.value) &&
                string.Equals(position.BFY, filter.value);
        }).Where(x => x.value != "" || x.value != null || x.value.ToUpper() != "ALL").Count() > 0;
    }

This works great, but I would be EXTREMELY impressed if I could globalize this so all my other data contracts could consume it!

Zacho
IF all your other contracts use a common base class or an interface then simply move the method to a static class and then pass in the base class or interface as a parameter instead of the staffing position data contract.
Peter
The classes do not share a base class, or an interface. I can change them to be that way, but since all the properties of each class are totally different, I'm not sure how to use this without a switch statement.
Zacho