获取外部程序集带自定义属性的属性时类型转换失败问题
反射获取外部类库自定义属性失败的解决方案
问题描述
创建了外部类库程序集,定义了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
相关产品推荐
相关产品推荐

