使用反射为静态类属性赋值触发System.Reflection.TargetException
问题场景
我正在为静态类添加方法,用于将非静态类实例的所有属性值复制到静态类的对应属性中,运行时抛出如下异常:
Exception thrown: 'System.Reflection.TargetException' in mscorlib.dll
System.Reflection.TargetException: Object does not match target type.
at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
at Dispensing.Classes.Options.CopyPropertiesFromSource(Object source) in C:\Users\erics\source\repos\TestingEFClassLibrary\TestingEFClassLibrary\Classes\Options.cs:line 32
原始代码
public static class Options { public static bool DispenseFile { get; set; } public static Units Units { get; set; } public static AppSettings AppSettings { get; set; } public static DispenseStyle DispenseStyle { get; set; } public static double Volume { get; set; } public static void CopyPropertiesFromSource(object source) { Type t = typeof(Options); var destinationProperties = t.GetProperties(BindingFlags.Static | BindingFlags.Public); var sourceProperties = source.GetType().GetProperties(); foreach (var destinationProperty in destinationProperties) { foreach (var sourceProperty in sourceProperties) { if (destinationProperty.Name == sourceProperty.Name && destinationProperty.PropertyType == sourceProperty.PropertyType) { try { Debug.WriteLine(destinationProperty.Name); destinationProperty.SetValue(t, sourceProperty.GetValue(sourceProperty)); } catch (Exception ex) { Debug.WriteLine(ex.ToString()); } break; } } } } }
报错位置
报错出现在以下代码行:
destinationProperty.SetValue(t, sourceProperty);
触发异常时目标属性和源属性均为Boolean类型,名称、类型完全匹配。
错误原因
两处调用参数错误导致类型不匹配:
- 静态属性的
SetValue方法第一个参数是目标实例,因为静态成员不属于任何实例,此处应传null,错误传入了Options的Type对象导致类型不匹配。 - 源属性取值方法
sourceProperty.GetValue的参数应为源实例对象source,错误传入了sourceProperty本身这个PropertyInfo对象,导致取值时类型不匹配。
修正方案
将报错行代码修改为如下内容即可解决问题:
destinationProperty.SetValue(null, sourceProperty.GetValue(source));
内容的提问来源于stack exchange,提问作者Eric Snyder

