c# - Filtering IEnumerable by collection (Linq) -
i want filter ienumerable object specific property of whatever object collecting. want alternative filter 1 or more property value but how many values (and values) filter known @ runtime.
ok, give example, collected objects next struct:
public struct person { public string name { get; set; } public string profession{ get; set; } } this struct used next list, have populated arbitrary values:
list<person> people= new list<person>; people.add(new person(){name = "mickey", profession="tinker"}; people.add(new person(){name = "donald", profession="tailor"}; people.add(new person(){name = "goofy", profession="soldier"}; people.add(new person(){name = "pluto", profession="spy"}; this set ienumerable (all of them transferred first)
var wantedpeople = n in this.people select n; so user interested in "tailor" , "spy" professions, , via sort of gui trickery next collection created:
list<string> wantedprofessions = new list<string>(); wantedprofessions.add("tailor"); wantedprofessions.add("spy"); now linq statement can utilize filer wantedpeople includes tailor , spy entries? know utilize clause don't know how tailor want (and doing next not want works wantedprofessions collection above (e.g. collection alter @ runtime):
wantedpeople = n in wantedpeople n.profession == wantedproffessions[0] || n.profession == wantedproffessions[1] select n;
if want check wanted profession given list:
wantedpeople = n in wantedpeople wantedproffessions.contains(n.profession) select n; or can build query lambda syntax applying filters 1 one:
var query = people.asenumerable(); if (!string.isnullorempty(name)) query = query.where(p => p.name == name); if (wantedprofessions.any()) query = query.where(p => wantedprofessions.contains(p.profession)); if wanted create more complex filters, name, , several professions, can utilize specification pattern. specification can defined simple interface:
public interface ispecification<t> { bool satisfied(t entity); } it checks whether given entity (person) satisfies specification. specification simple:
public class personnamespecification : ispecification<person> { private string _name; public personnamespecification(string name) { _name = name; } public bool satisfied(person person) { homecoming person.name == _name; } } profession specification:
public class personprofessionspecification : ispecification<person> { private string[] _professions; public personprofessionspecification(params string[] professions) { _professions = professions; } public bool satisfied(person person) { homecoming _professions.contains(person.profession); } } you can create specifications implement boolean logic, orspecification or andspecification:
public class andspecification<t> : ispecification<t> { private ispecification<t> _speca; private ispecification<t> _specb; public andspecification(ispecification<t> speca, ispecification<t> specb) { _speca = speca; _specb = specb; } public bool satisfied(t entity) { homecoming _speca.satisfied(entity) && _specb.satisfied(entity); } } public static class specificationextensions { public static ispecification<t> and<t>( ispecification<t> speca, ispecification<t> specb) { homecoming new andspecification<t>(speca, specb); } } now can create complex specification describes people want get:
var professionspec = new personprofessionspecification("tailor", "spy"); var namespec = new personnamespecification("pluto"); var spec = professionspec.and(namespec); and required people:
var result = people.where(spec.satisfied); c# linq
No comments:
Post a Comment