美文网首页unitycsharp
[教程] 基于 .asmref ,动态插入友元程序集新打法!!

[教程] 基于 .asmref ,动态插入友元程序集新打法!!

作者: 雨落随风 | 来源:发表于2024-06-14 04:57 被阅读0次

    在本文,你将学会在不侵入第三方程序集的情况下,你可以决定这个程序集对谁 Visible(成为它的友元程序集)!!!

    前言

    研究过不用反射访问位于其他程序集的 Internal修饰的成员的同学们都知道 友元程序集 是实现这个需求的近乎完美的解决方案,可是这就有个问题,人家程序集凭什么对你 Visible,或者说设计之初人家怎么知道有个你呢?

    常规方案

    有一个常规的解决办法,那就是在这个程序集中预设几个莫须有的程序集,以后有新写的程序集想要访问这个程序集中不公开的类型,你就委屈把程序集命名成之前预设的。

    Emmm... 感兴趣吗?
    巧了不是,这里恰好有个活生生的示例:UnityToolchainsTrick-Example_49_Friend

    如下图所示,Unity.InternalAPIEngineBridge.006 就是 UnityEditor.dll 内置的预设值友元程序集

    内置的预设友元程序集

    这样一来,使用 asmdef 声明一个与 Unity.InternalAPIEngineBridge.006 同名的程序集,这个新的程序集就能访问 UnityEditor.dll 内的内部(internal)成员啦!

    using UnityEditor;
    
    namespace UnityToolchinsTrick
    {
        public static class PlayerSettingBind
        {
            public static char[] PlayerSettingDefineSplits => PlayerSettings.defineSplits;
        }
    }
    
    • PlayerSettingBind 是用户自己声明的类型
    • PlayerSettings.defineSplits 是 UnityEditor.dll 一个 internal 成员,但现在也能访问啦~

    这种方式也太过于委曲求全了,一来不喜欢用别人的名称,太没个性;二来如果恰巧被其他人占用,那岂不是尴尬!

    全新打法

    铺垫这么多,下面就说说怎么实现由我来决定第三方程序集是否应该对我程序集 Visiable (友元)呢?

    实现原理

    1. 得益于 Unity Assembly Definition 、Assembly Definition References 机制,我们可以构建一个 Assembly Definition References 文件(.asmref 文件) ,然后指定目标程序集是那个第三方程序集,这样我们就可以无侵入的为这个程序集添加脚本了。
    2. 我们知道,在 .Net 托管的程序集中,存在 AssemblyInfo.cs 这样一个文件,程序集就是通过这个文件中的形如:[assembly: InternalsVisibleTo("Unity.PlasticSCM.EditorTests")] 语句知道谁是他的友元程序集,应该对谁可见!
    3. 通过上面的 2 个机制,我们就可以很方便的让任意 Assembly Definition 文件(.asmdef 文件)定义的第三方程序集对我们的程序集可见啦!

    实操演练

    1. 使用 A.asmdef 和 B.asmdef 文件定义 2 个新的程序集 A.dll 和 B.dll
    2. 在程序集 A 中随意写上一些内部和公开的成员
    3. 在程序集 B 所在资产目录中新建 Internal 文件夹,构建 .asmref 文件并指向 A.asmdef
    4. 在这个 Internal 文件夹中构建 AssemblyInfo.cs 并写下如下内容:
    [assembly: InternalsVisibleTo("B")]
    

    得到的资产结构如下:


    1. 在程序集 B 中新建测试脚本,尝试访问程序集 A 中的 内部成员

    2. 你会发现在不修改程序集 A 的任意资产情况下,就实现了程序集 B中访问程序集 A 内部成员!

    Before After
    1. 使用 ILSpy 反编译观察可见我们插入的对程序集 B 可见的相关信息:


    本文配套演示工程 Friend-Assembly-By-asmref

    写到最后

    1. 这种方法也有些限制,比如只能用在使用 Assembly Definition 定义的程序集;
    2. 程序集中已经存在 AssemblyInfo.cs 不会有任何问题,编译器会自动整合的哦!
    3. 当然,我也是偶然看到这种用法,觉得新奇还有用便行文记之,如果觉得有趣,留下你的赞吧!
    4. 如果你关注了 Unity 最新的多语言插件,你就会发现这种用法了


    版权所有,转载请注明出处!

    相关文章

      网友评论

        本文标题:[教程] 基于 .asmref ,动态插入友元程序集新打法!!

        本文链接:https://www.haomeiwen.com/subject/zynoqjtx.html