本文告诉大家 Resharper 家(JetBrains)开源的 Refasmer 工具,这个工具的功能就是从现有的 DLL 或 EXE 程序集里面,将所有的公开成员导出,重新打出新的 DLL 或 EXE 程序集。此时打出的新的程序集里面的方法都不包含实现,而是只有定义,这样的程序集被成为仅作为引用用途的程序集,也就是 Reference assemblies 的意思,这也就是 Refasmer 命名来源
这个 Refasmer 工具是是一个 dotnet tool 工具,安装非常方便,使用如下代码进行安装
接着咱用一个现有的 DLL 来测试一下用途,如我有一个叫 Lindexi.dll 文件,我采用如下命令行进行转换为仅作为引用用途的程序集
输入上面代码之后,将会在相同的文件夹下生成 Lindexi.dll.refasm.dll
文件,这个文件就是引用文件啦,不需要通过 dnspy 只通过文件的大小即可看出两个 DLL 的不同。在 dnspy 上可以看到 refasm.dll 里面只有方法的定义和属性的定义,但是没有任何具体的实现
这样的仅作为引用用途的程序集可以方便用在某些插件开发 SDK 或者某些不支持的版本上,用于构建用途。或者用在某些超大项目上,用于支持超大解决方案里面单个项目的独立构建
和 dotnet 自带的 ProduceOnlyReferenceAssembly 不同之处在于 Refasmer 可以从 DLL 里面导出仅作为引用用途的程序集。但 ProduceOnlyReferenceAssembly 是需要从源代码里面生成,更多关于 ProduceOnlyReferenceAssembly 请看 msbuild 使用 ProduceOnlyReferenceAssembly 创建作为引用的仅公开成员程序集
除了以上默认命令外,还可以给 refasmer 加上以下参数,用于实现更多功能
指定导出文件夹
默认的命令导出的是 refasm.dll
文件,显然这样的文件是不适合作为 NuGet 重新发布的,否则后续将会因为找不到对应的 DLL 而让运行时失败。但是如果文件命名上和之前的 DLL 相同,又会覆盖现有的文件
解决方法就是给定输出文件夹,通过 -O
参数,如下面代码
运行完成上面代码,可以在 foo 文件夹里面,找到 Lindexi.dll
文件,在这个 foo 文件夹里面的 dll 文件是仅作为引用用途的程序集
另外,如果只是想输出单个文件的,可以通过 -o
参数,这个参数用于重新设置文件名,如下面命令
执行以上代码,将会输出 LindexiDoubi.dll
程序集
安静运行
默认的 refasmer 也没啥输出,如果不想要有任何输出,请加入 -q
参数,如下面命令
输出调试信息
和 安静运行 不同的是,加上 -v
参数,输出更多信息
列举文件信息
加上 -l
参数或 --list
参数可以输出本次导出的文件信息,如下面命令
输出内容大概如下
更多命令和使用方法请看 JetBrains/Refasmer: The tool to create reference assembly from common assembly.
自定义
如果发现当前的命令行不符合需求,还可以自己动手写代码
先创建一个 .NET 控制台项目,接着通过 NuGet 安装 JetBrains.Refasmer 库
下面以创建此控制台项目的仅作为引用用途的程序集做例子,代码如下
以上代码通过传入 ToReferenceAssembly 方法给定 DLL 程序集和期望输出的文件路径,然后将会执行 Refasmer 库提供的方法,从 file 里面读取公开成员,写入到 output 文件
以上代码加上了 metaReader.IsAssembly
用于判断当前的 DLL 是否 dotnet 程序集
以上代码的 PEReader 是 dotnet 默认提供的机制,在 Refasmer 库里面核心用是这个进行读取程序集内容
调用 MetadataImporter.MakeRefasm 方法的输出就是 byte 数组,可以写入到文件
上面代码的 VerySimpleLogger 是自己定义的日志类,代码忽略。可以从下面了解如何拿到本文源代码
可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源
获取代码之后,进入 RairnarwayjallWhayderelaqea 文件夹
更多关于 Roslyn 请看 手把手教你写 Roslyn 修改编译
在 dotnet 6 时,默认都会生成仅引用程序集,用于决定上层引用项目是否需要重新构建。详细请参阅:
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。 欢迎转载、使用、重新发布,但务必保留文章署名 林德熙 (包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我 联系。