You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

根因分析

  1. 动态程序集重复加载:日志显示类型来自动态程序集,生产环境中这类程序集可能因热重载、动态编译等被多次加载。CLR会将不同加载上下文的同名称类型视为不同类型,导致PropertyInfo所属类型与目标对象类型不兼容。
  2. 共享资源线程安全问题:如果lookupModelProperty.Property是多线程共享的缓存资源,可能被意外修改,导致当前使用的PropertyInfo与目标对象类型不匹配。
  3. 动态代理包装: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 01:42:35