2009-06-04 8 views
3

J'ai besoin de filtrer une liste fortement typée de type StaffingPositionsDataContract, avec une autre liste de noms et de valeurs de filtres. J'ai ces deux listes:Comment filtrer une liste fortement typée avec la liste <String> variables

List<SerializedForm> deserializedObject = JsonConvert.DeserializeObject<List<SerializedForm>>(searchFilters).Where(x => !string.IsNullOrEmpty(x.value) && !string.Equals(x.value.ToUpper(), "ALL")).ToList(); 
    List<StaffingPositionsDataContract> staffingPositionResponse = new StaffingPositionsDataContract().LoadMockData(); 

L'objet deserialized a 2 propriétés. 1: "nom", 2: "valeur". Ces propriétés doivent être capables de filtrer plusieurs classes différentes avec des propriétés différentes. J'ai une méthode qui fonctionne si le StaffingPositionsDataContract en cours de filtrage est une chaîne, mais pas int ou decimal ou float. Voici ce que j'utilise qui fonctionne uniquement avec des filtres de chaîne.

private static List<T> _GetFilteredList<T, U>(IList<T> ListToFilter, string PropertyToFilterOn, List<U> FilterValues) 
    { 
     ParameterExpression p = Expression.Parameter(typeof(T), "x"); 

     Func<T, U> select = Expression.Lambda<Func<T, U>>(
      Expression.Property(p, PropertyToFilterOn), p).Compile(); 

     return ListToFilter.Join(FilterValues, select, u => u, (t, u) => t).ToList(); 
    } 

Voici comment cela se fait appeler:

var filteredPositions = staffingPositionResponse; 
     deserializedObject.ForEach(delegate(SerializedForm filters) 
     { 
      filteredPositions = _GetFilteredList<StaffingPositionsDataContract, string>(staffingPositionResponse, filters.name, new List<string> { filters.value }); 
     }); 

Quelqu'un sait comment je peux filtrer la classe staffingPositionResponse avec les objets deserializedObject?

+0

(commentaire) - pouvez-vous donner un exemple de comment vous l'appelez? Quelles sont les valeurs? Cela a fonctionné pour moi avec des ints, des ficelles et des flotteurs ... –

Répondre

3

Voici une application de console qui fait quelque chose de similaire. Vous devrez évaluer comment obtenir la sérialisation JSON appropriée à partir du formulaire de votre application. Je force simplement un dictionnaire dans une chaîne JSON à des fins de test.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Newtonsoft.Json; 
using System.Reflection; 

namespace FilterLists 
{ 
    public class Program 
    { 
     static void Main(string[] args) 
     { 
      // set up the bunk json 
      var filters = new Dictionary<string, object>(); 
      filters.Add("PositionId", "12345"); 
      string json = JsonConvert.SerializeObject(filters); 
      // what's it look like as a string? 
      Console.WriteLine(json); 

      // take the json string and stuff it to our method. 
      var result = GetStaffingPosition(json); 
      Console.WriteLine(result.Count); 
     } 

    public static List<StaffingPositionsDataContract> GetStaffingPosition(string searchFilters) 
    { 
     var filters = JsonConvert.DeserializeObject<Dictionary<string, object>>(searchFilters).ToList(); 
     var contracts = StaffingPositionsDataContract.LoadMockData(); 

     List<StaffingPositionsDataContract> result = new List<StaffingPositionsDataContract>(); 

     foreach (var filter in filters) 
     { 
      foreach (var contract in contracts) 
      { 
       PropertyInfo info = typeof(StaffingPositionsDataContract).GetProperty(filter.Key); 
       var propType = info.PropertyType; 

       if (info.GetValue(contract, null).Equals(Convert.ChangeType(filter.Value, propType))) 
       { 
        result.Add(contract); 
       } 
      } 
     } 

     return result; 
    } 
} 


[Serializable] 
public class StaffingPositionsDataContract 
{ 
    public int PositionId { get; set; } 
    public string Series { get; set; } 
    public string BFY { get; set; } 
    public string BudgetStatus { get; set; } 
    public string DutyStation { get; set; } 
    public string OrgLocation { get; set; } 
    public string BudgetingEntity { get; set; } 
    public string FieldName { get; set; } 

    public static List<StaffingPositionsDataContract> LoadMockData() 
    { 
     List<StaffingPositionsDataContract> staffingposition = new List<StaffingPositionsDataContract>() 
     { 
      new StaffingPositionsDataContract() {PositionId = 12345, Series="", BFY="FY2010", BudgetStatus="Actual", DutyStation="", OrgLocation="", BudgetingEntity=""}, 
      new StaffingPositionsDataContract() {PositionId = 67891, Series="", BFY="FY2011", BudgetStatus="Actual", DutyStation="", OrgLocation="", BudgetingEntity=""}, 
      new StaffingPositionsDataContract() {PositionId = 12345, Series="", BFY="FY2010", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""}, 
      new StaffingPositionsDataContract() {PositionId = 67892, Series="", BFY="FY2011", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""}, 
      new StaffingPositionsDataContract() {PositionId = 987654, Series="", BFY="FY2010", BudgetStatus="Projected", DutyStation="", OrgLocation="", BudgetingEntity=""} 
     }; 
     return staffingposition; 
    } 
} 
} 
2

Notez que vous ne devez utiliser cette approche que si vous ne pouvez pas connaître les noms de propriété au moment de la compilation; mais ce qui suit semble fonctionner:

public static IEnumerable<T> WhereAny<T, U>(
    this IEnumerable<T> ListToFilter, string PropertyToFilterOn, List<U> FilterValues) 
{ 
    ParameterExpression p = Expression.Parameter(typeof(T), "x"); 
    var methodCall = Expression.Call(   
     Expression.Constant(FilterValues, typeof(List<U>)), 
     typeof(List<U>).GetMethod("Contains"), 
     Expression.PropertyOrField(p, PropertyToFilterOn) 
    ); 
    return ListToFilter.Where(Expression.Lambda<Func<T,bool>>(methodCall, p).Compile()); 
} 
+0

J'ai le même problème avec cette méthode. L'erreur est "L'expression de type 'System.Int32' ne peut pas être utilisée pour le paramètre de type 'System.String' de la méthode 'Boolean Contient (System.String)'" – Zacho

Questions connexes