.NET Emit中对象数组参数类型转换异常的解决方案咨询
问题:DynamicInvoke调用委托时的参数类型转换异常
相关定义代码
public class Message { public SayType Say(string name) { Console.Write("Hello," + name ); return SayType.Name; } } public enum SayType { Name }
出现问题的代码
public delegate SayType SayDelegate(Message message, params object[] o); public void Test() { DynamicMethod dynamicMethod = new DynamicMethod("Say", typeof(SayType), new Type[]{typeof(Message), typeof(object)}); var il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Ldarg, 0); il.Emit(OpCodes.Ldarg, 1); il.Emit(OpCodes.Ldc_I4, 0); il.Emit(OpCodes.Ldelem_Ref); il.Emit(OpCodes.Castclass, typeof(string)); il.Emit(OpCodes.Callvirt, typeof(Message).GetMethods()[0]); il.Emit(OpCodes.Ret); System.Delegate delegates = dynamicMethod.CreateDelegate(typeof(SayDelegate)); delegates.DynamicInvoke(new Message(), "b"); }
异常信息
Unhandled exception. System.ArgumentException: Object of type 'System.String' cannot be converted to type 'System.Object[]'.
解决方案
异常根源有两个:
- DynamicMethod参数类型不匹配:委托
SayDelegate的第二个参数是params object[] o,本质是object[]类型,但创建DynamicMethod时把第二个参数定义成了typeof(object),导致委托与动态方法的参数签名不兼容。 - DynamicInvoke参数传递错误:
DynamicInvoke会将传入的每个参数直接映射到委托的参数列表,传入的"b"是string类型,但委托期望第二个参数是object[],类型不匹配。
修改步骤:
1. 修正DynamicMethod的参数类型
将动态方法的参数列表中的第二个类型改为typeof(object[]),匹配委托的参数签名:
DynamicMethod dynamicMethod = new DynamicMethod("Say", typeof(SayType), new Type[]{typeof(Message), typeof(object[])});
原IL逻辑无需修改,因为它本来就是处理object[]类型的参数,取索引0的元素并转换为string。
2. 修正委托调用方式
有两种可选方式:
- 推荐:强类型委托调用:直接将创建的委托转换为
SayDelegate类型调用,利用params特性可以直接传入string参数,编译器会自动包装为object[]:SayDelegate del = (SayDelegate)dynamicMethod.CreateDelegate(typeof(SayDelegate)); del(new Message(), "b"); - 保留DynamicInvoke的调用方式:需要将
"b"包装为object[]传入,匹配委托的参数要求:delegates.DynamicInvoke(new Message(), new object[]{"b"});
内容的提问来源于stack exchange,提问作者DamXosp4j
相关产品推荐
相关产品推荐

