当前位置: 首页 > news >正文

仅反射加载(ReflectionOnlyLoadFrom)的 .NET 程序集,如何反射获取它的 Attribute 元数据呢?

平时我们获取一个程序集或者类型的 Attribute 是非常轻松的,只需要通过 GetCustomAttribute 方法就能拿到实例然后获取其中的值。但是,有时我们仅为反射加载一些程序集的时候,获取这些元数据就不那么简单了,因为我们没有加载目标程序集中的类型。

本文介绍如何为仅反射加载的程序集读取 Attribute 元数据信息。


本文内容

    • 仅反射加载一个程序集
    • 获取程序集的 Attribute(例如获取程序集版本号)

仅反射加载一个程序集

使用 ReflectionOnlyLoadFrom 可以仅以反射的方式加载一个程序集。

var extensionFilePath = @"C:\Users\walterlv\Desktop\Walterlv.Extension.dll";
var assembly = Assembly.ReflectionOnlyLoadFrom(extensionFilePath);

获取程序集的 Attribute(例如获取程序集版本号)

Assembly.GetCustomAttributesData() 得到的是一个 CustomAttributeData 的列表,而这个列表中的每一项都与普通反射中拿到的特性集合不同,这里拿到的只是特性的信息(以下循环中的 data 变量)。

CustomAttributeData 中有 AttributeType 属性,虽然此属性是 Type 类型的,但是实际上它只会是 RuntimeType 类型,而不会是真实的 Attribute 的类型(因为不能保证宿主程序域中已经加载了那个类型)。

var customAttributesData = assembly.GetCustomAttributesData();
foreach (CustomAttributeData data in customAttributesData)
{
    // 这里可以针对每一个拿到的慝的信息进行操作。
}

比如我们要获取这个程序集的版本号,正常我们写 assembly.GetCustomAttribute<AssemblyFileVersionAttribute>().Version,但是这里我们无法生成 AssemblyFileVersionAttribute 的实例,我们只能这么写:

var versionString = assembly.GetCustomAttributesData()
    .FirstOrDefault(x => x.AttributeType.FullName == typeof(AssemblyFileVersionAttribute).FullName)
    ?.ConstructorArguments[0].Value as string ?? "0.0";
var version = new Version(versionString);

代码解读是这样的:

  1. 我们从拿到的所有的 Attribute 元数据中找到第一个名称与 AssemblyFileVersionAttribute 相同的数据;
  2. 从数据的构造函数参数中找到传入的参数值,而这个值就是我们定义 AssemblyFileVersionAttribute 时传入的参数的实际值。

因为我们知道 AssemblyFileVersionAttribute 的构造函数只有一个,所以我们确信可以从第一个参数中拿到我们想要的值。

顺便一提,我们使用 AssemblyFileVersionAttribute 而不是使用 AssemblyVersionAttribute 是因为使用 .NET Core 新格式(基于 Microsoft.NET.Sdk)编译出来的程序集默认是不带 AssemblyVersionAttribute 的。详见:语义版本号(Semantic Versioning) - walterlv。


参考资料

  • CustomAttributeData Class (System.Reflection) - Microsoft Docs
  • c# - How to get custom attributes from an assembly that is not (really) loaded - Stack Overflow
  • c# - Get custom attribute data from assembly file and unlock it afterwise - Stack Overflow

我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

相关文章:

  • 全局或为单独的项目添加自定义的 NuGet 源
  • 电脑总是意外从睡眠状态唤醒,可以找出原因然后解决
  • 我收集的各种公有 NuGet 源
  • 制作一个极简的 .NET 客户端应用自安装或自更新程序
  • 在 MSBuild 编译项目时阻止输出所有的警告信息
  • 编写 MSBuild 内联编译任务(Task)用于获取当前编译环境下的所有编译目标(Target)
  • 如何在 csproj 中用 C# 代码写一个内联的编译任务 Task
  • 安装和运行 .NET Core 版本的 PowerShell
  • 让你的 Windows 应用程序在任意路径也能够直接通过文件名执行
  • 如何为你的 Windows 应用程序关联一种或多种文件类型
  • 如何为你的 Windows 应用程序关联 URL 协议,以便在浏览器中也能打开你的应用
  • 四种方法获取可执行程序的文件路径(.NET Core / .NET Framework)
  • 如何使用 MyGet 这个激进的 NuGet 源体验日构建版本的 .NET Standard / .NET Core
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • 为什么 C# 的 string.Empty 是一个静态只读字段,而不是一个常量呢?
  • [NodeJS] 关于Buffer
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Brief introduction of how to 'Call, Apply and Bind'
  • CentOS 7 修改主机名
  • Hexo+码云+git快速搭建免费的静态Blog
  • Java的Interrupt与线程中断
  • miaov-React 最佳入门
  • nodejs调试方法
  • QQ浏览器x5内核的兼容性问题
  • Spark学习笔记之相关记录
  • tweak 支持第三方库
  • 阿里云购买磁盘后挂载
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 聊聊flink的TableFactory
  • 使用parted解决大于2T的磁盘分区
  • 收藏好这篇,别再只说“数据劫持”了
  • 手写一个CommonJS打包工具(一)
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • ​第20课 在Android Native开发中加入新的C++类
  • ​一些不规范的GTID使用场景
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (二)JAVA使用POI操作excel
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (三) diretfbrc详解
  • (数据结构)顺序表的定义
  • (五)Python 垃圾回收机制
  • (转载)hibernate缓存
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .FileZilla的使用和主动模式被动模式介绍
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .NET 反射的使用
  • .NET简谈设计模式之(单件模式)