i need programmatically recognize when indexer occurs within expression, resulting expression tree not expected.
class indexedpropertiestest { static void main( string[] args ) { new indexedpropertiestest(); } public string this[int index] { { return list[index]; } set { list[index] = value; } } list<string> list = new list<string>(); public indexedpropertiestest() { test( () => this[0] ); } void test( expression<func<string>> expression ) { var nodetype = expression.body.nodetype; var methodname = ((methodcallexpression)expression.body).method.name; } } in above code, nodetype "call" , methodname "get_item". why? shouldn't expression.body equivalent expression.property( expression.constant( ), "item", expression.constant( 0 ) )? that's expected.
i need ability detect indexer in general way - given expression. mangling of intended expression tree compromises ability that. relying on method name being "get_item" far brittle. plus, indexernameattribute may have been used rename indexer property anyway.
so there anyway compiler generate intended expression tree? please don't suggest manually building expression, not option. or there way programmatically sure have indexer?
i think have answer: that's way c# compiler works.
i translated code vb.net. unhelpfully enough, vb.net doesn't call method get_item, rather calls name give it. in below example, ends get_mydefaultproperty.
sub main dim x indexedpropertiestest = new indexedpropertiestest() end sub ' define other methods , classes here class indexedpropertiestest private list new list(of string) { "a" } default property mydefaultproperty(index integer) string return list(index) end set(value string) list(index) = value end set end property public sub new test( function() me(0)) end sub public sub test(expression expression(of func(of string))) dim nodetype expressiontype = expression.body.nodetype dim methodname string = ctype(expression.body, methodcallexpression).method.name 'expression.dump() 'using linqpad end sub end class however, not lost: can write visitor try stuff get_item call indexexpression. started on here:
public class propertyfixervisitor : expressionvisitor { protected override expression visitmethodcall(methodcallexpression node) { if (node.method.name.startswith("get_")) { var possibleproperty = node.method.name.substring(4); var properties = node.method.declaringtype.getproperties() .where(p => p.name == possibleproperty); //hack: need filter out overriden properties, multiple parameter choices, etc. var property = properties.firstordefault(); if (property != null) return expression.property(node.object, possibleproperty, node.arguments.toarray()); return base.visitmethodcall(node); } else return base.visitmethodcall(node); } } you can safely modify test method so:
void test(expression<func<string>> expression) { var visitor = new propertyfixervisitor(); var modexpr = (expression<func<string>>)visitor.visit(expression); var indexexpression = (modexpr.body indexexpression); //not null }
Comments
Post a Comment