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

自定义MemberInfo类型VariableInfo使用Attribute.IsDefined()失效问题

问题原因与解决办法

问题根源

.NET Framework的BCL(基础类库)内部方法(比如Attribute.IsDefined)在处理MemberInfo时,是直接根据对象的实际类型进行硬转换,而非调用你在C#层面定义的显式转换运算符。

你的VariableInfo虽然继承了MemberInfo,且返回了正确的MemberType(比如属性对应MemberTypes.Property),但它本质上还是VariableInfo类型的实例,并非真正的PropertyInfo或FieldInfo。当BCL内部代码根据MemberType尝试将其强转为对应类型时,自然会抛出InvalidCastException——CLR只认对象的 runtime 类型,不认C#语法层面的自定义转换逻辑。

解决办法

方案1:改用组合模式封装(推荐)

放弃让VariableInfo继承MemberInfo,改为内部持有FieldInfo或PropertyInfo实例,对外暴露需要的方法和属性,内部直接委托给封装的实例。这种方式完全避开BCL的强转逻辑,从根源上解决问题。

示例代码:

public class VariableInfo
{
    private readonly MemberInfo _innerMember;

    public VariableInfo(FieldInfo field) => _innerMember = field;
    public VariableInfo(PropertyInfo property) => _innerMember = property;

    // 替代Attribute.IsDefined的实例方法
    public bool IsAttributeDefined(Type attributeType, bool inherit = false)
    {
        return Attribute.IsDefined(_innerMember, attributeType, inherit);
    }

    // 按需暴露MemberInfo的核心属性
    public string Name => _innerMember.Name;
    public MemberTypes MemberType => _innerMember.MemberType;
    public Type DeclaringType => _innerMember.DeclaringType;
}

方案2:重写MemberInfo的虚方法,委托给内部实例

如果必须让VariableInfo继承MemberInfo,可以重写MemberInfo中所有与属性相关的虚方法,内部直接调用封装的FieldInfo/PropertyInfo实例的对应方法。注意不要直接使用Attribute.IsDefined静态方法,而是调用VariableInfo自身重写的IsDefined方法。

示例代码:

public class VariableInfo : MemberInfo
{
    private readonly MemberInfo _innerMember;

    public VariableInfo(FieldInfo field) => _innerMember = field;
    public VariableInfo(PropertyInfo property) => _innerMember = property;

    // 重写属性相关方法
    public override bool IsDefined(Type attributeType, bool inherit)
    {
        return _innerMember.IsDefined(attributeType, inherit);
    }

    public override object[] GetCustomAttributes(bool inherit)
    {
        return _innerMember.GetCustomAttributes(inherit);
    }

    public override object[] GetCustomAttributes(Type attributeType, bool inherit)
    {
        return _innerMember.GetCustomAttributes(attributeType, inherit);
    }

    // 重写所有必要的属性和抽象方法
    public override string Name => _innerMember.Name;
    public override MemberTypes MemberType => _innerMember.MemberType;
    public override Type DeclaringType => _innerMember.DeclaringType;
    public override Type ReflectedType => _innerMember.ReflectedType;

    public override int GetHashCode() => _innerMember.GetHashCode();
    public override bool Equals(object obj) => _innerMember.Equals(obj);
    public override string ToString() => _innerMember.ToString();
}

使用时直接调用实例方法:

var variableInfo = new VariableInfo(someProperty);
bool hasAttr = variableInfo.IsDefined(typeof(MyAttribute), false);

方案3:直接传入内部封装的MemberInfo实例

如果只是偶尔需要调用BCL的静态方法,可以在VariableInfo中暴露内部的真实MemberInfo实例,调用时直接传入该实例而非VariableInfo本身。

示例代码:

public class VariableInfo : MemberInfo
{
    private readonly MemberInfo _innerMember;
    // 暴露内部实例
    public MemberInfo UnderlyingMember => _innerMember;

    // 其他构造和重写代码...
}

调用BCL方法时:

var variableInfo = new VariableInfo(someProperty);
bool hasAttr = Attribute.IsDefined(variableInfo.UnderlyingMember, typeof(MyAttribute));

内容的提问来源于stack exchange,提问作者A person

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 20:45:08