Cuando uso Expression.Lambda(...).Compile()
para crear un delegado de un árbol de expresiones, el resultado es un delegado cuyo primer argumento es Closure
.La compilación de una expresión lambda da como resultado un delegado con el argumento Closure
public static Func<T, T, T> CreateTest<T>()
{
ParameterExpression a = Expression.Parameter(typeof(T));
ParameterExpression b = Expression.Parameter(typeof(T));
Expression addition = Expression.Add(a, b);
return (Func<T, T, T>)Expression.Lambda(addition, a, b).Compile();
}
...
// 'addition' equals
// Int32 lambda_method(
// System.Runtime.CompilerServices.Closure,
// Int32,
// Int32)
Func<int, int, int> addition = DelegateHelper.CreateTest<int>();
int result = addition(5, 5);
puedo llamar fácilmente a través del delegado código ordinaria sin pasar un objeto Closure
, pero ¿de dónde viene esta Closure
viene?
¿Cómo puedo llamar a este delegado dinámicamente?
// The following does not work.
// Exception: MethodInfo must be a runtime MethodInfo object.
MethodInfo additionMethod = addition.Method;
int result = (int)additionMethod.Invoke(null, new object[] { 5, 5 });
El uso de árboles de expresión se ve como si tuviera que pasar el objeto Closure
.
PropertyInfo methodProperty
= typeof(Delegate).GetProperty("Method", typeof(MethodInfo));
MemberExpression getDelegateMethod
= Expression.Property(Expression.Constant(addition), methodProperty);
Func<MethodInfo> getMethodInfo
= (Func<MethodInfo>)Expression.Lambda(getDelegateMethod).Compile();
// Incorrect number of arguments supplied for call to method
// 'Int32 lambda_method(System.Runtime.CompilerServices.Closure, Int32, Int32)'
Expression call
= Expression.Call(
getMethodInfo(),
Expression.Constant(5), Expression.Constant(5));
Este es un ejemplo simplificado que no tiene sentido en sí mismo. Lo que en realidad estoy tratando de lograr es poder envolver, por ejemplo, Func<Action<SomeObject>>
con Func<Action<object>>
. Ya puedo hacer esto para delegados no anidados. Esto es útil durante la reflexión, as discussed here.
¿Cómo debo inicializar correctamente este objeto Closure
, o cómo puedo evitar que esté allí?
¿Podría dar un ejemplo corto pero * completo *? No es realmente obvio cuál es el problema. –
@JonSkeet: Haré mi mejor esfuerzo, el problema es que el ejemplo total es bastante complejo. Intento llamar a un delegado previamente compilado recursivamente. Mientras trato de extraer un pequeño subconjunto del problema, [aquí] (http://pastebin.com/53f0VqnF) ya puede encontrar la función completa. –
Sí, hacerlo más corto sin duda ayudaría :) –