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

PropertyType无法匹配接口及自身类型:动态装配引发的Swagger过滤问题

问题解决:Swagger SchemaFilter 无法过滤动态生成程序集中的IEntity属性

问题背景

为了在Swagger API文档中忽略所有实现IEntity接口的属性,编写了如下SchemaFilter:

Public Class cSwaggerIgnoreNavigationProperties
    Implements ISchemaFilter

    Public Sub Apply(voSchema As OpenApiSchema, voContext As SchemaFilterContext) Implements ISchemaFilter.Apply
        If voSchema.Properties.Count = 0 Then
            Return
        End If

        Const oFlags = BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public

        Dim oPropertyList = voContext.Type.GetProperties(oFlags)

        Dim oExcludedList =
            oPropertyList.Where(Function(p) p.PropertyType.IsAssignableTo(GetType(IEntity))) _
                .Select(Function(p)
                            Dim oCamelCaser As cCamelCaser = New cCamelCaser()
                            Return If(p.GetCustomAttribute(Of JsonPropertyNameAttribute)()?.Name, oCamelCaser.ToLowerCamelCase(p.Name))
                        End Function)

        For Each sExcluded In oExcludedList
            If voSchema.Properties.ContainsKey(sExcluded) Then
                voSchema.Properties.Remove(sExcluded)
            End If
        Next
    End Sub
End Class

多数场景下该过滤器工作正常,但部分类型(如S4D_Data.Patient,该类型继承自实现IEntity的基类)的属性未被正确过滤。

调试异常现象

调试时发现针对S4D_Data.Patient类型的属性,p.PropertyType.IsAssignableTo(GetType(IEntity))返回False:

?p.PropertyType.FullName
"S4D_Data.Patient"
?p.PropertyType.IsAssignableTo(GetType(S4D_Data.IEntity))
False

但直接检查类型本身时结果正常:

?GetType(S4D_Data.Patient).IsAssignableTo(GetType(S4D_Data.IEntity))
True

更异常的是,反射得到的PropertyType实例无法匹配自身类型:

?p.PropertyType.IsAssignableTo(GetType(S4D_Data.Patient))
False
?p.PropertyType = GetType(S4D_Data.Patient)
False

问题根源

进一步排查确认,系统加载了两个包含S4D_Data.Patient类型的程序集:

  • 原始程序集:S4D_Data.Patient, S4D Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
  • 动态生成程序集:S4D_Data.Patient, V2e56f2547b0f45d2a33a0d70b908a55e.DynamicModels, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

反射获取的属性类型来自动态生成程序集,而GetType(IEntity)指向的是原始程序集中的接口,两者属于不同程序集实例,导致类型匹配逻辑失效。

解决方案

修改类型判断逻辑,通过类型全名+接口全名进行匹配,摆脱对程序集实例的依赖:

Public Class cSwaggerIgnoreNavigationProperties
    Implements ISchemaFilter

    Public Sub Apply(voSchema As OpenApiSchema, voContext As SchemaFilterContext) Implements ISchemaFilter.Apply
        If voSchema.Properties.Count = 0 Then
            Return
        End If

        Const oFlags = BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public
        ' 获取目标接口的全名(包含命名空间)
        Dim targetInterfaceFullName = GetType(IEntity).FullName

        Dim oPropertyList = voContext.Type.GetProperties(oFlags)

        Dim oExcludedList =
            oPropertyList.Where(Function(p) 
                ' 遍历属性类型实现的所有接口,通过全名匹配目标接口
                Return p.PropertyType.GetInterfaces().Any(Function(i) i.FullName = targetInterfaceFullName)
            ) _
                .Select(Function(p)
                            Dim oCamelCaser As cCamelCaser = New cCamelCaser()
                            Return If(p.GetCustomAttribute(Of JsonPropertyNameAttribute)()?.Name, oCamelCaser.ToLowerCamelCase(p.Name))
                        End Function)

        For Each sExcluded In oExcludedList
            If voSchema.Properties.ContainsKey(sExcluded) Then
                voSchema.Properties.Remove(sExcluded)
            End If
        Next
    End Sub
End Class

逻辑说明

  1. 先获取IEntity接口的完整名称(包含命名空间),作为匹配基准
  2. 对每个属性类型,遍历其实现的所有接口,通过接口全名判断是否符合过滤条件
  3. 该方式不依赖程序集加载实例,只要类型实现了同全名的接口就能被正确识别

内容的提问来源于stack exchange,提问作者Daniel Vernall

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:53:20