c# - Recognize indexer in LINQ expression -


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