前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >dotnet 使用 Refasmer 从现有的 DLL 里面导出公开的成员组装出新的仅作为引用用途的程序集

dotnet 使用 Refasmer 从现有的 DLL 里面导出公开的成员组装出新的仅作为引用用途的程序集

作者头像
林德熙
发布2021-12-23 11:04:28
5820
发布2021-12-23 11:04:28
举报
文章被收录于专栏:林德熙的博客

本文告诉大家 Resharper 家(JetBrains)开源的 Refasmer 工具,这个工具的功能就是从现有的 DLL 或 EXE 程序集里面,将所有的公开成员导出,重新打出新的 DLL 或 EXE 程序集。此时打出的新的程序集里面的方法都不包含实现,而是只有定义,这样的程序集被成为仅作为引用用途的程序集,也就是 Reference assemblies 的意思,这也就是 Refasmer 命名来源

这个 Refasmer 工具是是一个 dotnet tool 工具,安装非常方便,使用如下代码进行安装

代码语言:javascript
复制
dotnet tool install -g JetBrains.Refasmer.CliTool

接着咱用一个现有的 DLL 来测试一下用途,如我有一个叫 Lindexi.dll 文件,我采用如下命令行进行转换为仅作为引用用途的程序集

代码语言:javascript
复制
refasmer 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 参数,如下面代码

代码语言:javascript
复制
refasmer Lindexi.dll -O foo

运行完成上面代码,可以在 foo 文件夹里面,找到 Lindexi.dll 文件,在这个 foo 文件夹里面的 dll 文件是仅作为引用用途的程序集

另外,如果只是想输出单个文件的,可以通过 -o 参数,这个参数用于重新设置文件名,如下面命令

代码语言:javascript
复制
refasmer Lindexi.dll -o LindexiDoubi.dll

执行以上代码,将会输出 LindexiDoubi.dll 程序集

安静运行

默认的 refasmer 也没啥输出,如果不想要有任何输出,请加入 -q 参数,如下面命令

代码语言:javascript
复制
refasmer Lindexi.dll -O foo -q

输出调试信息

和 安静运行 不同的是,加上 -v 参数,输出更多信息

代码语言:javascript
复制
refasmer Lindexi.dll -O foo -v

列举文件信息

加上 -l 参数或 --list 参数可以输出本次导出的文件信息,如下面命令

代码语言:javascript
复制
refasmer Lindexi.dll -l

输出内容大概如下

代码语言:javascript
复制
<?xml version="1.0" encoding="Codepage - 936"?>
<FileList>
  <File AssemblyName="Lindexi" Version="1.1.0.0" Culture="neutral" PublicKeyToken="0902d2af90156091" InGac="false" ProcessorArchitecture="MSIL" />
</FileList>

更多命令和使用方法请看 JetBrains/Refasmer: The tool to create reference assembly from common assembly.

自定义

如果发现当前的命令行不符合需求,还可以自己动手写代码

先创建一个 .NET 控制台项目,接着通过 NuGet 安装 JetBrains.Refasmer 库

代码语言:javascript
复制
  <ItemGroup>
    <PackageReference Include="JetBrains.Refasmer" Version="1.0.12" />
  </ItemGroup>

下面以创建此控制台项目的仅作为引用用途的程序集做例子,代码如下

代码语言:javascript
复制
        static void Main(string[] args)
        {
            var file = Assembly.GetExecutingAssembly().Location;
            var output = file + Path.GetRandomFileName();

            ToReferenceAssembly(file, output);
        }

        private static void ToReferenceAssembly(string file, string output)
        {
            using var peReader = new PEReader(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read));
            var metaReader = peReader.GetMetadataReader();
            if (metaReader.IsAssembly)
            {
                var result =
                    MetadataImporter.MakeRefasm(metaReader, peReader, new LoggerBase(new VerySimpleLogger(Console.Out)));

                File.WriteAllBytes(output, result);
            }
        }

以上代码通过传入 ToReferenceAssembly 方法给定 DLL 程序集和期望输出的文件路径,然后将会执行 Refasmer 库提供的方法,从 file 里面读取公开成员,写入到 output 文件

以上代码加上了 metaReader.IsAssembly 用于判断当前的 DLL 是否 dotnet 程序集

以上代码的 PEReader 是 dotnet 默认提供的机制,在 Refasmer 库里面核心用是这个进行读取程序集内容

调用 MetadataImporter.MakeRefasm 方法的输出就是 byte 数组,可以写入到文件

上面代码的 VerySimpleLogger 是自己定义的日志类,代码忽略。可以从下面了解如何拿到本文源代码

本文所有代码放在 githubgitee 欢迎访问

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

代码语言:javascript
复制
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 1b9b1a70f93fe065db216472d96a095eb7d39983

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源

代码语言:javascript
复制
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

获取代码之后,进入 RairnarwayjallWhayderelaqea 文件夹

更多关于 Roslyn 请看 手把手教你写 Roslyn 修改编译

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 指定导出文件夹
  • 安静运行
  • 输出调试信息
  • 列举文件信息
  • 自定义
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档