He pasado por un tiempo y me he golpeado la cabeza contra la pared por un tiempo ahora he buscado varias frases y palabras clave pero no encuentro nada parecido a una respuesta así que espero que alguien aquí pueda arrojar algo de luz.¿Por qué no puedo crear el mismo Árbol de Expresión manualmente que mi lambda recta produce
Básicamente estoy trabajando en el buceo bastante profundamente en manipular, crear y modificar los árboles de expresión en C# 4.0
me encontré con una anomalía extraña que no puedo dar sentido a
si escribo algo como esto
Expression<Func<string,string>> InsertAString = (Insert) => "This " + (Insert == "" ? "" : Insert + " ") + "That";
Cuando llego a depurar y miro el árbol de expresión que es similar a esto
- F (NodeType = Lambda)
- cuerpo (NodeType = Añadir)
- Izquierda (NodeType = Añadir)
- Izquierda (NodeType = constante, Valor = "Este")
- derecho (NodeType = condicional)
- ifFalse (NodeType = Añadir)
- izquierda (NodeType = Parámetro, Name = "Insertar")
- derecho (NodeType = constante, Valor = " ")
- ifTrue (NodeType = constante, Valor = "")
- prueba (NodeType = Igual)
- Izquierda (NodeType = parámetros, cuyo nombre = "Insertar")
- derecho (NodeType = constante, Valor = "")
- ifFalse (NodeType = Añadir)
- derecho (NodeType = constante, Valor = "Eso")
- Izquierda (NodeType = Añadir)
- Paramerters (Count = 1)
- Parámetros [0] (NodeType = Parámetro, Name = "Insertar")
- cuerpo (NodeType = Añadir)
puedo llamar
Console.WriteLine(InsertAString.Compile()("Is Something In-between"));
y salga como espero
"Esto es algo intermedio que"
Ahora bien, si lo intento y reconstruir esa forma manual utilizando los métodos estáticos de la clase base Expresión me encuentro con un tema interesante.(He desglosado cada paso en su propia expresión para propósitos de depuración)
ParameterExpression Insert = Expression.Parameter(typeof(object), "Insert");
ConstantExpression This = Expression.Constant("This ");
ConstantExpression That = Expression.Constant("That");
ConstantExpression Space = Expression.Constant(" ");
ConstantExpression NoCharacter = Expression.Constant("");
BinaryExpression InsertPlusSpace = Expression.Add(Insert,Space);
BinaryExpression InsertEqualsNoCharacter = Expression.Equal(Insert,NoCharacter);
ConditionalExpression InsertPlusSpaceOrNothing = Expression.IfThenElse(InsertEqualsNoCharacter,NoCharacter,InsertPlusSpace);
BinaryExpression ThisPlusInsertPlusSpaceOrNothing = Expression.Add(This,InsertPlusSpaceOrNothing);
BinaryExpression ThisPlusInsertPlusSpaceOrNothingPlusThat = Expression.Add(ThisPlusInsertPlusSpaceOrNothing, That);
Lambda Lambda = Expression.Lambda(ThisPlusInsertPlusSpaceOrNothingPlusThat, Middle);
Expression<Func<string,string>> InsertAString = Lambda as Expression<Func<string,string>>
que en base a los valores del árbol de expresión generada por encima de recrear el mismo árbol expresión básica que el anterior (al menos con el mismo "look")
Todo pasos a través de bien hasta que llegan a esta línea
BinaryExpression InsertPlusSpace = Expression.Add(Insert,Space);
El compilador lanza un InvalidOperationException era no controlada
El operador binario Agregar no está definido para 'System.String' y 'System.String'
Ahora ¿por qué es esto?
¿Por qué cuando dejo que C# convierta un Lambda en Expression obviamente usa el Add NodeType, y la pantalla de Tipos muestra que definitivamente está usando System.String pero cuando intento hacer lo mismo manualmente no deja que el código ¿continuar?
Como nota final incluso he intentado lo siguiente:
BinaryExpression InsertPlusSpace = Expression.MakeBinary(ExpressionType.Add,Insert,Space);
mismo error.
Tengo curiosidad por lo que parece al menos con lo que he podido encontrar hasta ahora que la concatenación de cadenas en los árboles de expresiones solo funciona si no se intenta construir manualmente un árbol de expresiones que agregue constantes y variables de tipo Sistema. Cuerda.
Gracias a todos por adelantado por las respuestas.
+1, pero para mayor claridad, un ejemplo conciso: 'Expression.Add (Expression.Constant (" a "), Expression.Constant (" b "), typeof (string)) .GetMethod ("Concat", nuevo [] {typeof (cadena), typeof (cadena)})); ' –
Ya sabes, apúntate esto a simple deb ug ceguera. Lo volví a ejecutar. Nunca pensé en mirar la Propiedad del Método 8-O Sin embargo, ahí está System.String.Concat .... Gracias por la respuesta rápida que me aclara :-) – TofuBug