C#反射调用DLL方法传递结构体参数报错的解决办法
反射调用DLL传递结构体时类型转换异常的解决
问题场景
反射动态调用DLL时,传递结构体参数触发如下异常:
System.ArgumentException: Object of type 'MRaport' cannot be converted to type 'MRaport'.
本地代码:
public struct MRaport { public int rapId; public string rapName; public string Level; } private void CreateRap() { Assembly assembly = Assembly.LoadFrom(@"path\RapLibrary.dll"); Type myLibraryType = assembly.GetType("XReport"); object myLibraryInstance = Activator.CreateInstance(myLibraryType); bool x = true; MRaport mr = new MRaport { rapId = 1, rapName = "MxFolder", Level = "Red" }; MethodInfo methodInfo = myLibraryType.GetMethod("fillRaport"); object[] parameters = new object[] { x, mr }; try { string result = (string)methodInfo.Invoke(myLibraryInstance, parameters); MessageBox.Show(result); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
类库(RapLibrary.dll)代码:
public struct MRaport { public int rapId; public string rapName; public string Level; } public class XReport { public string fillRaport(bool x, MRaport mr) { if (x) { return mr.rapName; } else { return mr.Level; } } }
问题原因
本地代码和DLL中分别定义了同名同结构但分属不同程序集的MRaport结构体,CLR会将它们视为完全独立的类型,因此传递参数时触发类型不匹配异常。
解决方法
方法1:共享结构体定义(推荐)
将MRaport结构体抽离到独立的共享类库(如SharedModels.dll),让本地项目和RapLibrary.dll项目同时引用该类库。这样两边使用的是同一个程序集下的MRaport类型,参数传递时不会出现类型冲突。
修改后本地代码无需重复定义结构体:
// 直接引用SharedModels.dll中的MRaport类型 private void CreateRap() { Assembly assembly = Assembly.LoadFrom(@"path\RapLibrary.dll"); Type myLibraryType = assembly.GetType("XReport"); object myLibraryInstance = Activator.CreateInstance(myLibraryType); bool x = true; MRaport mr = new MRaport { rapId = 1, rapName = "MxFolder", Level = "Red" }; MethodInfo methodInfo = myLibraryType.GetMethod("fillRaport"); object[] parameters = new object[] { x, mr }; try { string result = (string)methodInfo.Invoke(myLibraryInstance, parameters); MessageBox.Show(result); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
RapLibrary.dll代码同样改为引用共享类库的MRaport:
// 引用SharedModels.dll中的MRaport类型 public class XReport { public string fillRaport(bool x, MRaport mr) { if (x) { return mr.rapName; } else { return mr.Level; } } }
方法2:动态创建DLL中的结构体实例
如果无法使用共享类库,可以从加载的DLL中获取MRaport类型,动态创建实例并赋值后再传递:
private void CreateRap() { Assembly assembly = Assembly.LoadFrom(@"path\RapLibrary.dll"); Type myLibraryType = assembly.GetType("XReport"); object myLibraryInstance = Activator.CreateInstance(myLibraryType); // 获取DLL内部的MRaport类型 Type raportType = assembly.GetType("MRaport"); bool x = true; // 动态创建DLL中MRaport的实例 object mrInstance = Activator.CreateInstance(raportType); // 给结构体字段赋值 raportType.GetField("rapId").SetValue(mrInstance, 1); raportType.GetField("rapName").SetValue(mrInstance, "MxFolder"); raportType.GetField("Level").SetValue(mrInstance, "Red"); MethodInfo methodInfo = myLibraryType.GetMethod("fillRaport"); object[] parameters = new object[] { x, mrInstance }; try { string result = (string)methodInfo.Invoke(myLibraryInstance, parameters); MessageBox.Show(result); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
内容的提问来源于stack exchange,提问作者Wals
相关产品推荐
相关产品推荐

