C#反射调用GetValue获取对象属性值报TargetException异常
问题根因
你代码报错的核心原因有两个,直接触发TargetException的是GetValue方法的参数传错:
PropertyInfo.GetValue()的第一个入参要求传入属性所属的目标对象实例,也就是你的localStorageProfile,不是属性名的字符串。你传入"name"、"photoUrl"这类字符串后,反射调用属性get方法时,发现目标实例是string类型,和属性声明所属的类型不匹配,直接抛出你看到的类型不匹配异常。- 循环逻辑完全错误:你要读取的是固定两个名称的属性,不需要遍历对象的所有属性。你当前的写法会在每一轮循环(包括遍历到id、imagePublicId等无关属性时)都重复给
userprofile.Name和userprofile.PhotoUrl赋值,哪怕参数传对也会出现值被错误覆盖的问题。
修正方案
写法1(推荐,不需要遍历,性能更好)
直接通过属性名获取对应的PropertyInfo对象,传入正确的实例参数取值即可:
Type targetType = localStorageProfile.GetType(); // 按属性名获取属性元数据,注意属性名大小写严格匹配 PropertyInfo? nameProp = targetType.GetProperty("name"); PropertyInfo? photoProp = targetType.GetProperty("photoUrl"); // 取值赋值,加空判断避免空引用异常 if (nameProp != null) { userprofile.Name = nameProp.GetValue(localStorageProfile)?.ToString(); } if (photoProp != null) { userprofile.PhotoUrl = photoProp.GetValue(localStorageProfile)?.ToString(); }
写法2(保留遍历逻辑的修正版)
如果你就是想通过遍历熟悉反射用法,需要在循环内先判断当前遍历到的属性名,再传入正确实例取值:
foreach (var p in localStorageProfile.GetType().GetProperties()) { switch(p.Name) { case "name": userprofile.Name = p.GetValue(localStorageProfile)?.ToString(); break; case "photoUrl": userprofile.PhotoUrl = p.GetValue(localStorageProfile)?.ToString(); break; } }
补充说明:取值时建议用
?.ToString()代替直接调用.ToString(),你给出的对象结构里存在imagePublicId这类值为null的属性,如果直接调用ToString()会触发空引用异常。另外C#反射获取属性时名称大小写敏感,传入的属性名字符串必须和实际属性名完全一致,否则会拿到null的PropertyInfo对象。
内容的提问来源于stack exchange,提问作者Eduard
相关产品推荐
相关产品推荐

