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

获取外部程序集带自定义属性的属性时类型转换失败问题

反射获取外部类库自定义属性失败的解决方案

问题描述

创建了外部类库程序集,定义了MyCustomAttribute自定义属性和Class1类。尝试通过反射获取Class1中带MyCustomAttribute的属性时,两种方法均失败:

  • 使用Attribute.IsDefined筛选返回null
  • 遍历属性获取自定义属性后,转换为ClassLibrary1.MyCustomAttribute时返回null,尽管调试显示该属性确实是MyCustomAttribute类型

类库代码

namespace ClassLibrary1
{
    public class MyCustomAttribute : Attribute
    {
        public string Message { get; set; }
    }

    public class Class1
    {
        public int MyProperty0 { get; set; }

        [MyCustom(Message = "aaa")]
        public int MyProperty1 { get; set; }

        [MyCustom(Message = "bbb")]
        public int MyProperty2 { get; set; }
    
        public int MyProperty3 { get; set; }
    }
}

尝试的代码

代码1

Assembly assembly = Assembly.LoadFile(<file path>);
var props = assembly.GetType("ClassLibrary1.Class1").GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(ClassLibrary1.MyCustomAttribute)));

代码2

PropertyInfo[] props = assembly.GetType("ClassLibrary1.Class1").GetProperties();
foreach (PropertyInfo prop in props)
{
    object[] attrs = prop.GetCustomAttributes(false);
    foreach (object attr in attrs)
    {
        var authAttr = attr as ClassLibrary1.MyCustomAttribute; // 转换后为null
        if (authAttr != null)
        {
            string propName = prop.Name;
            string message = authAttr.Message;

            Console.WriteLine($"{propName} ... {message }");
        }
    }
}

问题根源

核心原因是程序集重复加载导致类型不匹配:
如果主项目已直接引用ClassLibrary1,同时又通过Assembly.LoadFile加载同一个dll,CLR会将这两个加载的程序集视为独立实体,对应的MyCustomAttribute类型会被判定为不同类型,因此类型转换会失败。

解决方法

方法1:避免重复加载(推荐)

若主项目已引用ClassLibrary1,直接使用项目中已存在的类型,无需动态加载程序集:

var props = typeof(ClassLibrary1.Class1).GetProperties().Where(
    prop => Attribute.IsDefined(prop, typeof(ClassLibrary1.MyCustomAttribute)));

// 遍历输出示例
foreach (var prop in props)
{
    var attr = prop.GetCustomAttribute<ClassLibrary1.MyCustomAttribute>();
    Console.WriteLine($"{prop.Name} ... {attr.Message}");
}

方法2:完全动态加载(无项目引用时)

若必须动态加载程序集,不要依赖项目中的类型定义,全程用反射操作:

Assembly assembly = Assembly.LoadFile(<file path>);
Type classType = assembly.GetType("ClassLibrary1.Class1");
Type attrType = assembly.GetType("ClassLibrary1.MyCustomAttribute");

PropertyInfo[] props = classType.GetProperties();
foreach (PropertyInfo prop in props)
{
    // 直接筛选指定类型的属性
    object[] attrs = prop.GetCustomAttributes(attrType, false);
    foreach (object attr in attrs)
    {
        // 通过反射获取Message属性值
        PropertyInfo messageProp = attrType.GetProperty("Message");
        string message = messageProp?.GetValue(attr) as string;
        Console.WriteLine($"{prop.Name} ... {message}");
    }
}

方法3:检查程序集加载路径

确保Assembly.LoadFile加载的dll与项目引用的是同一文件,避免因版本或路径不同导致的重复加载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 01:41:04