I need to programmatically recognize when an indexer occurs within an expression, but the resulting expression tree is not what I expected.
class IndexedPropertiesTest
{
static void Main( string[] args ) { new IndexedPropertiesTest(); }
public string this[int index]
{
get { 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 the above code, nodeType is "Call" and methodName is "get_Item". Why? Shouldn't expression.Body be equivalent to Expression.Property( Expression.Constant( this ), "Item", Expression.Constant( 0 ) )? That's what I expected.
I need the ability to detect an indexer in a very general way - given just about any expression. This mangling of the intended expression tree compromises my ability to do that. Relying on the method name being "get_Item" is far too brittle. Plus, IndexerNameAttribute may have been used to rename the indexer property anyway.
So is there anyway to get the compiler to generate the intended expression tree? Please don't suggest manually building the expression, as that is not an option. Or is there any way to programmatically be sure that what I have is an indexer?
I think you have your answer: That's the way the C# compiler works.
I translated your code into VB.NET. Unhelpfully enough, VB.NET doesn't call the method
get_Item, rather it calls it by the name you give it. In the below example, that ends up withget_MyDefaultProperty.However, all is not lost: You can write a Visitor to try to stuff the
get_Itemcall back into anIndexExpression. I started on it here:You can then safely modify your Test method as so: