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

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

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

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


本文内容

    • 仅反射加载一个程序集
    • 获取程序集的 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

代码解读是这样的:

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

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

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



参考资料



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

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

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


walter lv

博客专家

发布了382 篇原创文章 · 获赞 232 · 访问量 47万+

私信
关注

原文地址:https://www.cnblogs.com/lonelyxmas/p/12052011.html

时间: 2024-11-10 08:21:17

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

C#关于反射加载的问题

三个程序集: 主程序集:BaseApp.exe 接口程序集:IBaseApplication 插件程序集:TestAttri ======================================================================================= 在接口程序中: 接口:IApp 属性定义:ModuleAttribute 复制代码代码如下: public interface IApp : IMothed { void ParentForm(IA

Quartz.net 2.x 学习笔记03-使用反射加载定时任务

将定时任务信息存储在XML文件中,使用反射加载定时任务 首先新建一个MVC的空站点,使用NuGet添加对Quartz.net和Common.Logging.Log4Net1213的引用,同时使用NuGet管理器控制台执行命令更新log4net,PM> update-package log4net 接着在解决方案中添加一个类库Library项目 类库项目也添加对Quartz.net的引用 下面可以编写代码了,在Library类库中添加一个JobBase类,3个Job类,和一个Job管理类(假设分别

C#使用反射加载多个程序集

当开发插件的时候需要用到反射,在客户端动态加载遍历程序集,并调用每个程序集的方法. 创建一个控制台应用程序,首先设计一个接口: public interface ISay { void SaySth(); } 在控制台应用程序下创建Plugins文件夹,控制台的可执行文件和所有程序集文件都生成在这里.右键控制台项目--"属性"--"生成",把"输出路径"设置成Plugins文件夹. 创建类库项目Assembly1,添加对控制台项目的引用,并创建实

利用反射加载类

反射:java.lang.reflect 要被加载的类: package eg.fortest; public class WaitingforLoader { private String str; static{ System.out.println("loading WaitingforLoader"); } public WaitingforLoader() { str="empty"; System.out.println("Constructo

(转帖)关于easyui中的datagrid在加载数据时候报错:无法获取属性&quot;Length&quot;的值,对象为null或未定义

结贴说明: 很感谢sp1234等人的热心帮忙和提醒,现在我主要说明下问题所在: 首先我在独立的js文件中,直接把测试数据loaddata进去datagrid是没有问题的.var kk = {"total":2,"rows":[{"INSTANCE_ID":"BI00000011","BUSINESS_NAME":"专项检查文档资料报送","INSTANCE_STATUS&quo

iOS 利用webView加载html代码,在代理中获取html页面的链接时出现的问题

getDetailWebview.loadHTMLString(webViewData as String, baseURL:NSURL(string: "\(ProBaseWeb)")) 当用webView的loadHEMLString方法加载html代码时,必须设置baseURL,否则执行代理方法获取页面链接URL时得到的URL会在前部自动天剑如下字段: applewebdata://C97726ED-D607-4CD6-A49C-A86E8598E421/:如果获取的url是一个

android listView 滑动加载数据 该数据是服务端获取的

package com.sunway.works.applycash; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; import com.sunway.works.R; import com.sunway.works.applycash.ApplyCashListActivity; impo

Unity3D Android动态反射加载程序集

这种办法在iOS下是不让用的,只能在Android下用.用起来也很方便了. 1.先创建一个c#工程,引用到的UnityEngine.dll在Unity的安装目录里找吧 2.将编译的dll放入Unity工程,并打成assetBundle.(要把缀名改成.bytes,这个类型Unity才识别,才能打成assetbundle) 打bundle代码 #if UNITY_EDITOR [MenuItem("GameObject/BuildAsset")] static void BuildAss

Clr Via C#读书笔记---程序集的加载和反射

#1 加载程序集 Assembly.Load: public class Assembly { public static Assembly Load(AssemblyName assemblyRef); public static Assembly Load(String assemblyString); } 在内部,Load导致CLR向应用程序集应用一个版本绑定重定向策略,并在GAC中查找程序集.如果传递的是一个弱命名程序集,不会应用版本绑定重定向策略,也不会去GAC中查找程序集. AppD