Estoy tratando de dar un pequeño ejemplo de IDynamicMetaObjectProvider
para la segunda edición de C# en profundidad, y estoy teniendo problemas.¿Cómo se expresa una llamada al método void como resultado de DynamicMetaObject.BindInvokeMember?
Quiero expresar una llamada anulada, y estoy fallando. Estoy seguro de que es posible, porque si llamo dinámicamente a un método nulo usando la carpeta de reflexión, todo está bien. He aquí una breve pero completa ejemplo:
using System;
using System.Dynamic;
using System.Linq.Expressions;
class DynamicDemo : IDynamicMetaObjectProvider
{
public DynamicMetaObject GetMetaObject(Expression expression)
{
return new MetaDemo(expression, this);
}
public void TestMethod(string name)
{
Console.WriteLine(name);
}
}
class MetaDemo : DynamicMetaObject
{
internal MetaDemo(Expression expression, DynamicDemo demo)
: base(expression, BindingRestrictions.Empty, demo)
{
}
public override DynamicMetaObject BindInvokeMember
(InvokeMemberBinder binder, DynamicMetaObject[] args)
{
Expression self = this.Expression;
Expression target = Expression.Call
(Expression.Convert(self, typeof(DynamicDemo)),
typeof(DynamicDemo).GetMethod("TestMethod"),
Expression.Constant(binder.Name));
var restrictions = BindingRestrictions.GetTypeRestriction
(self, typeof(DynamicDemo));
return new DynamicMetaObject(target, restrictions);
}
}
class Test
{
public void Foo()
{
}
static void Main()
{
dynamic x = new Test();
x.Foo(); // Works fine!
x = new DynamicDemo();
x.Foo(); // Throws
}
}
Esto arroja una excepción:
Excepción no controlada: System.InvalidCastException: El tipo resultado 'System.Void' de la Enlace dinámico producido por el objeto con tipo 'DynamicDemo' para la carpeta 'Microsoft.CSharp.RuntimeBinder.CSharpInvokeMemberBinder' no es compatible con el tipo de resultado 'System.Object' esperado por el sitio de llamada .
Si cambio el método para devolver el objeto y devolver null, que funciona bien ... pero no quiero que el resultado sea nulo, yo quiero que sea nula. Eso funciona bien para la carpeta de reflexión (ver la primera llamada en Main) pero falla para mi objeto dinámico. Quiero que funcione como la carpeta de reflexión: está bien llamar al método, siempre y cuando no intentes usar el resultado.
¿He perdido un tipo particular de expresión que puedo usar como objetivo?
Hablando de tirar un guante ... –
Jon Skeet hizo una pregunta ... y todavía no se ha respondido correctamente. Es el fin del mundo tal como lo conocemos. –
@Marc: Mi última pregunta con suerte terminará con un error solucionado para el lanzamiento de .NET 4.0 ... ¿quién sabe lo que sucederá esta vez? :) –