仅反射加载(ReflectionOnlyLoadFrom)的 .NET 程序集,如何反射获取它的 Attribute 元数据呢?
原文:仅反射加载(ReflectionOnlyLoadFrom)的 .NET 程序集,如何反射获取它的 Attribute 元数据呢?
平时我们获取一个程序集或者类型的 Attribute
是非常轻松的,只需要通过 GetCustomAttribute
方法就能拿到实例然后获取其中的值。但是,有时我们仅为反射加载一些程序集的时候,获取这些元数据就不那么简单了,因为我们没有加载目标程序集中的类型。
本文介绍如何为仅反射加载的程序集读取 Attribute 元数据信息。
仅反射加载一个程序集
使用 ReflectionOnlyLoadFrom
可以仅以反射的方式加载一个程序集。
var extensionFilePath = @"C:\Users\walterlv\Desktop\Walterlv.Extension.dll";
var assembly = Assembly.ReflectionOnlyLoadFrom(extensionFilePath);
- 1
- 2
获取程序集的 Attribute(例如获取程序集版本号)
Assembly.GetCustomAttributesData()
得到的是一个 CustomAttributeData
的列表,而这个列表中的每一项都与普通反射中拿到的特性集合不同,这里拿到的只是特性的信息(以下循环中的 data
变量)。
CustomAttributeData
中有 AttributeType
属性,虽然此属性是 Type
类型的,但是实际上它只会是 RuntimeType
类型,而不会是真实的 Attribute
的类型(因为不能保证宿主程序域中已经加载了那个类型)。
var customAttributesData = assembly.GetCustomAttributesData();
foreach (CustomAttributeData data in customAttributesData)
{
// 这里可以针对每一个拿到的慝的信息进行操作。
}
- 1
- 2
- 3
- 4
- 5
比如我们要获取这个程序集的版本号,正常我们写 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
- 2
- 3
- 4
代码解读是这样的:
- 我们从拿到的所有的
Attribute
元数据中找到第一个名称与AssemblyFileVersionAttribute
相同的数据; - 从数据的构造函数参数中找到传入的参数值,而这个值就是我们定义
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/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
仅反射加载(ReflectionOnlyLoadFrom)的 .NET 程序集,如何反射获取它的 Attribute 元数据呢?的更多相关文章
- Unity热更新之C#反射加载程序集
用C#反射加载程序集的方式可以动态的从assetBundle资源包或其他资源包里加载脚本到工程中,即便是原工程中不存在的脚本. 我这里就用加载本地assetBundle的方式来进行讲解了,加载网络上的 ...
- Quartz.net 2.x 学习笔记03-使用反射加载定时任务
将定时任务信息存储在XML文件中,使用反射加载定时任务 首先新建一个MVC的空站点,使用NuGet添加对Quartz.net和Common.Logging.Log4Net1213的引用,同时使用NuG ...
- c# 动态加载和卸载DLL程序集
原文:c# 动态加载和卸载DLL程序集 在 C++中加载和卸载DLL是一件很容易的事,LoadLibrary和FreeLibrary让你能够轻易的在程序中加载DLL,然后在任何地方卸载.在 C#中我们 ...
- WPF 反射加载Geometry几何图形数据图标
相信大家在阅读WPF相关GitHub开源项目源码时都会看见一串串这种数据 这种Geometry数据就是几何图形数据 为什么要用Geometry数据做图标? 有一种做法是使用ttf字体文件代替,不过使用 ...
- C#使用反射加载多个程序集
当开发插件的时候需要用到反射,在客户端动态加载遍历程序集,并调用每个程序集的方法. 创建一个控制台应用程序,首先设计一个接口: public interface ISay { void SaySth( ...
- 对tomcat中使用反射加载类的理解
public void init() throws Exception { initClassLoaders(); //加载一下jar包和类 Thread.currentThread().setCon ...
- 反射01 Class类的使用、动态加载类、类类型说明、获取类的信息
0 Java反射机制 反射(Reflection)是 Java 的高级特性之一,是框架实现的基础. 0.1 定义 Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对 ...
- .Net6新版本的AssemblyLoadContext 加载程序集和卸载程序集
准备俩个项目 第一个是控制台 第二个项目是类库 类库项目中只有一个示例class 将类库的代码生成dll 并且设置属性为复制到输出目录 using System.Runtime.Loader; var ...
- iOS 利用webView加载html代码,在代理中获取html页面的链接时出现的问题
getDetailWebview.loadHTMLString(webViewData as String, baseURL:NSURL(string: "\(ProBaseWeb)&quo ...
随机推荐
- linux 排查cpu负载过高异常
步骤一.找到最耗CPU的进程 工具:top 方法: 执行top -c ,显示进程运行信息列表 键入P (大写p),进程按照CPU使用率排序 图示: 如上图,最耗CPU的进程PID为10765 步骤二: ...
- UIAutomatorViewer、Inspector获取元素信息
一.UIautomatorViewer 它是Android SDK的一个工具,如果安装了 Android SDK,就可以在cmd窗口直接输入uiautomatorviewer打开. 点击左上角的第二个 ...
- Netty通信网络参数配置
Netty服务端/客户端网络通信过程中常用的参数: Name Associated setter method "writeBufferHighWaterMark" 默认64 * ...
- python lambda表达式简单用法【转】
python lambda表达式简单用法 1.lambda是什么? 看个例子: g = lambda x:x+1 看一下执行的结果: g(1) >>>2 g(2) >>& ...
- Fragment: 使用newInstance()来实例化fragment(转)
先说结论: 1. 当需要给Fragment传值时,使用newInstance()方式来实例化一个Fragment,能够更好的将该Fragment使用的参数捆绑起来,不必每次实例化时都写下面的代码: B ...
- 【Python】解析Python中函数的基本使用
1.简介 在Python中定义函数的基本格式为: def <函数名>(参数列表): <函数语句> return <返回值> Python中的函数形式比较灵活,声明一 ...
- asp.netcore Log4Net连接kafka的方法
1.NuGet添加2个包: Microsoft.Extensions.Logging.Log4Net.AspNetCore log4net.Kafka.Core 2.Program里修改CreateW ...
- Eureka Server 集群配置
注册中心: debug: true spring: application: name: eureka-server logging: level: com.netflix.eureka: 'off' ...
- fragment原来的页面切换被重新实例化,无法继续保持上一次的内容。只让它执行一次
最好的方法是: 定义类.静态变量的方式 保存数据,从这里取. 用网上其他人的方法,fragment切换速度太快会报错 child view 没有从parent view 中移除: 只执行一次,定义一个 ...
- sqlite3 数据库表查看步骤
sqlite3 数据库表查看步骤 1 sqlite3 local.db2 .mode column3 .headers on4 .tables5 select * from tablename6 ;( ...