C#反射类型哈希码匹配却抛出TargetException问题排查
生产环境反射获取属性值偶发TargetException问题排查
生产环境中,以下反射获取属性值的代码偶尔会触发TargetException,但开发/测试环境无法复现。日志显示PropertyInfo.ReflectedType与目标对象childModel的类型哈希码、程序集限定名完全一致,但仍报错“Object does not match target type”。
相关代码
try { attributeValue = lookupModelProperty.Property.GetValue(childModel); } catch (System.Reflection.TargetException ex) { throw new Exception($"Site 4 modelAttribute.Property.Name: {modelAttribute.Property.Name} " + $"modelAttribute.Property.ReflectedType.AssemblyQualifiedName: {modelAttribute.Property.ReflectedType.AssemblyQualifiedName} " + $"modelAttribute.Property.ReflectedType.GetHashCode: {modelAttribute.Property.ReflectedType.GetHashCode()} " + $"childModel.GetType().AssemblyQualifiedName: {childModel.GetType().AssemblyQualifiedName} " + $"childModel.GetType().GetHashCode: {childModel.GetType().GetHashCode()} " , ex); }
报错日志
Error: System.Exception: Site 4 modelAttribute.Property.Name: XXXPropertyName modelAttribute.Property.ReflectedType.AssemblyQualifiedName: XXXClassName, DynamicAssembly_XXXAssemblyNamespace, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null modelAttribute.Property.ReflectedType.GetHashCode: 39642089 childModel.GetType().AssemblyQualifiedName: XXXClassName, DynamicAssembly_XXXAssemblyNamespace, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null childModel.GetType().GetHashCode: 39642089 ---> 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)
根因分析
- 动态程序集重复加载:日志显示类型来自动态程序集,生产环境中这类程序集可能因热重载、动态编译等被多次加载。CLR会将不同加载上下文的同名称类型视为不同类型,导致
PropertyInfo所属类型与目标对象类型不兼容。 - 共享资源线程安全问题:如果
lookupModelProperty.Property是多线程共享的缓存资源,可能被意外修改,导致当前使用的PropertyInfo与目标对象类型不匹配。 - 动态代理包装:
childModel可能是动态代理生成的实例(如EF代理、Castle DynamicProxy),表面类型与ReflectedType一致,但底层存在继承/包装关系,触发反射校验失败。
解决方案
- 从目标对象类型重新获取PropertyInfo:避免复用缓存的
PropertyInfo,确保类型上下文一致:try { var targetType = childModel.GetType(); var property = targetType.GetProperty(lookupModelProperty.Property.Name); attributeValue = property?.GetValue(childModel); } catch (System.Reflection.TargetException ex) { // 保留原有日志逻辑 } - 增加类型兼容性校验:调用
GetValue前用IsAssignableFrom校验,而非仅对比哈希码和名称:if (!lookupModelProperty.Property.ReflectedType.IsAssignableFrom(childModel.GetType())) { var property = childModel.GetType().GetProperty(lookupModelProperty.Property.Name); attributeValue = property?.GetValue(childModel); } else { attributeValue = lookupModelProperty.Property.GetValue(childModel); } - 优化动态程序集加载逻辑:排查生产环境动态程序集的生成机制,避免重复加载同类型的动态程序集。
内容的提问来源于stack exchange,提问作者Jonathan.S
相关产品推荐
相关产品推荐

