[英]RuntimeBinderException invoking a method on a generic type as dynamic
I'm trying to invoke a method on a generic type (generic is also an argument to invoking method) and are hitting RuntimeBinderException
that I don't really see how to work around.我正在尝试在泛型类型上调用一个方法(泛型也是调用方法的一个参数)并且遇到了
RuntimeBinderException
,我真的不知道如何解决。
As you can see in below example the instance returns the MyHandler
instance (as a dynamic
) which I expect to get invoked, but without explicit conversion to the generic type of the DTO ( as MyDto
) it will crash.正如您在下面的示例中看到的那样,该实例返回
MyHandler
实例(作为dynamic
),我希望调用它,但是如果没有显式转换为 DTO 的泛型类型( as MyDto
),它将崩溃。 And my requirement is to determine the type in runtime (as I see the JsonConvert.DeserializeObject(data, type)
does, until the point of invocation).我的要求是确定运行时的类型(正如我看到的
JsonConvert.DeserializeObject(data, type)
所做的那样,直到调用点)。
static async Task Main(string[] args)
{
string dataType = typeof(MyDto).AssemblyQualifiedName;
string data = JsonConvert.SerializeObject(new MyDto());
var type = Type.GetType(dataType);
var dto = JsonConvert.DeserializeObject(data, type);
var handler = GetHandler();
await handler.HandleMessageAsync(dto, CancellationToken.None); // throws the RuntimeBinderException
await handler.HandleMessageAsync(dto as MyDto, CancellationToken.None); // is able to invoke MyHandler.HandleMessageAsync
}
public static dynamic GetHandler()
{
// this is simplified logic for locating a handler instance.
return new MyHandler();
}
The exception thrown in the 1st invocation from example is示例的第一次调用中引发的异常是
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'The best overloaded method match for 'ConsoleApp.MessageHandlerBase<ConsoleApp.MyDto>.HandleMessageAsync(ConsoleApp.MyDto, System.Threading.CancellationToken)' has some invalid arguments'
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:'ConsoleApp.MessageHandlerBase<ConsoleApp.MyDto>.HandleMessageAsync(ConsoleApp.MyDto, System.Threading.CancellationToken)' 的最佳重载方法匹配有一些无效参数'
I don't see how the conversion can make a change to the DTO as they are the same type.我看不到转换如何更改 DTO,因为它们是相同的类型。 So, my question is how I can succeed invoking the method completely dynamically?
所以,我的问题是我怎样才能成功地完全动态地调用该方法?
This is the simplified DTO and handler service class hierarchy of the real implementation:这是实际实现的简化 DTO 和处理程序服务 class 层次结构:
public class MyDto
{
public int Prop1 { get; set; } = 1;
}
public interface IMessageHandler<in T> where T : class
{
Task HandleMessageAsync(T dto, CancellationToken cancellationToken);
}
public class MyHandler : IMessageHandler<MyDto>
{
public Task HandleMessageAsync(MyDto dto, CancellationToken cancellationToken)
{
Console.WriteLine("OnError called from " + this);
return Task.CompletedTask;
}
}
Can you please try changing type of dto variable from object to dynamic as below -您能否尝试将 dto 变量的类型从 object 更改为动态,如下所示 -
dynamic dto = JsonConvert.DeserializeObject(data, type);
The final code should something like this -最终的代码应该是这样的 -
static async Task Main(string[] args)
{
string dataType = typeof(MyDto).AssemblyQualifiedName;
string data = JsonConvert.SerializeObject(new MyDto());
var type = Type.GetType(dataType);
dynamic dto = JsonConvert.DeserializeObject(data, type); // declare as dynamic instead of var (declaring as var would default to object type)
var handler = GetHandler();
await handler.HandleMessageAsync(dto, CancellationToken.None); // throws the RuntimeBinderException
await handler.HandleMessageAsync(dto as MyDto, CancellationToken.None); // is able to invoke MyHandler.HandleMessageAsync
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.