c# - Create expression tree to assign to property of list -
c# - Create expression tree to assign to property of list -
this has been plaguing me days now....
if have list of own object searchresults
, searchresults contains multiple lists of objects, of have match (bool) property, how can recreate look tree accomplish following:
//searchresults list<searchresults> searchresults[i].comments = searchresults[i].comments.select(p1 => { p1.match = listofstringvariable.all(p2 => { string value = (string)typeof(commentdata).getproperty(propertyname).getvalue(p1); homecoming value.contains(p2); }); homecoming p1; }).orderbydescending(x => x.match); .... public class searchresults { public ienumerable<commentdata> comments { get; set; } public ienumerable<advisordata> advisors { get; set; } } public class commentdata { public string commenttext { get; set; } public bool match { get; set; } } public class advisordata { public string firstname { get; set; } public string lastname { get; set; } public bool match { get; set; } }
the look tree needed won't know property @ compile-time needs assigned, whether comments, advisors, etc (as simplification of larger problem). above illustration comments, how same code used assign advisors without having conditional block?
many thanks
update:
so far using reflection have below striplingwarrior
var searchresult = searchresults[i]; foreach (var srproperty in searchresultsproperties) { var collectiontype = srproperty.propertytype; if(!collectiontype.isgenerictype || collectiontype.getgenerictypedefinition() != typeof(ienumerable<>)) { throw new invalidoperationexception("all searchresults properties should ienumerable<something>"); } var itemtype = collectiontype.getgenericarguments()[0]; var itemproperties = itemtype.getproperties().where(p => p.name != "match"); var items = ((ienumerable<ihavematchproperty>) srproperty.getvalue(searchresult)) // materialize enumerable, in case it's backed // re-create objects each time it's iterated over. .tolist(); foreach (var item in items) { var propertyvalues = itemproperties.select(p => (string)p.getvalue(item)); item.match = propertyvalues.any(v => searchterms.any(v.contains)); } var ordereditems = items.orderby(i => i.match); srproperty.setvalue(srproperty, ordereditems); }
however ordereditems
of type system.linq.orderedenumerable<ihavematchproperty,bool>
, needs cast ienumerable<advisordata>
. below throws error:
'system.linq.enumerable.castiterator(system.collections.ienumerable)' 'method' used 'type'
var castmethod = typeof(enumerable).getmethod("cast").makegenericmethod(new[] {propertytype}); var result = castmethod.invoke(null, new[] { ordereditems });
where propertytype
type advisordata
first, create types implement interface don't have quite much reflection:
public interface ihavematchproperty { bool match { get; set; } }
then write code this. (i'm making lot of assumptions because question wasn't super clear on intended behavior is.)
var searchresult = searchresults[i]; foreach (var srproperty in searchresultsproperties) { var collectiontype = srproperty.propertytype; if(!collectiontype.isgenerictype || collectiontype.getgenerictypedefinition() != typeof(ienumerable<>)) { throw new invalidoperationexception("all searchresults properties should ienumerable<something>"); } var itemtype = collectiontype.getgenericarguments()[0]; var itemproperties = itemtype.getproperties().where(p => p.name != "match"); var items = ((ienumerable<ihavematchproperty>) srproperty.getvalue(searchresult)) // materialize enumerable, in case it's backed // re-create objects each time it's iterated over. .tolist(); foreach (var item in items) { var propertyvalues = itemproperties.select(p => (string)p.getvalue(item)); item.match = propertyvalues.any(v => searchterms.any(v.contains)); } var ordereditems = items.orderby(i => i.match); srproperty.setvalue(srproperty, ordereditems); }
c# lambda expression-trees
Comments
Post a Comment