はじめに
今回はコンパイル後のdllに対してリフレクションを利用せずにasmrefを使ってinternalにアクセスする方法について紹介したいと思います。
この記事を見ている方ならasmrefについての説明は大丈夫かと思いますが、一応前書いておいた記事を貼っておきます。
www.hanachiru-blog.com
とても便利なasmrefですが、コンパイル前でなければアセンブリにコードを埋め込むことはできません。(つまりasmdefが定義されてないとダメ)
ですのでコンパイル済のdllに対してはasmrefを使って直接internalの利用することができないのです。しかしちょっと邪道?なやり方でそれを擬似的に実現できる場合があります。
概要
コンパイル済であったとしても、アセンブリの中にInternalsVisibleToが記載されていれば希望があります。

やり方としてはInternalsVisibleToに含まれているアセンブリにasmdefが定義されていたら、そこにasmrefを用いてコードをアセンブリに組み込むことで、間接的に対象アセンブリのinternalにアクセスします。
以下実験で用いたアセンブリの関係性を載せておきます。

例えば上記サンプルのTargetSample.dllとHoge.asmdefのどちらもUnityが提供しているパッケージであったと考えます。ユーザーが書いたSample.csはTargetSample.dllのinternalにアクセスしようとしたらまずリフレクションが候補にあがります。
しかしよくコードをみるとTargetSample.dllにはInternalVisibleToが定義されており、Hoge.asmdefからはinternalにアクセスできることに気がつきました。
というわけでasmrefを利用してHoge.asmdefにコードを組み込めば、間接的にTargetSample.dllのinternalにアクセスできるというわけです。
実験
dllを作成する
Riderで適当なdllを生成します。このとき重要なのはHogeという名前のアセンブリからのみinternalにアクセスできるようにしておきます。
using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Hoge")] namespace TargetSample { public class SampleClass { public int PublicMethod() { return 1; } internal int InternalMethod() { return 2; } private int PrivateMethod() { return 3; } } }
生成したdllをUnityにインポートしておきます。

Hoge.asmdefを定義する
Hoge.asmdefからは当然TargetSample.dllのinternalにアクセスすることが可能です。
private void Start() { var sampleClass = new SampleClass(); // 当然publicにアクセスできる sampleClass.PublicMethod(); // internalにアクセスできる sampleClass.InternalMethod(); // privateにはアクセスできない // sampleClass.PrivateMethod(); }

asmrefでHoge.asmdefにコードを組み込む
asmrefを用いてHoge.asmdefにコードを組み込むことで間接的にinternalをアクセスしていきます。

private void Start() { var sampleClass = new SampleClass(); // asmrefでHoge.asmdefにコードが組み込まれるのでinternalにアクセスできる sampleClass.InternalMethod(); }
さいごに
リフレクションは処理が重いだけでなく、コンパイル時にエラーが出てこなかったりとなるべく使いたくないものです。internalということはそれだけ変更もされやすいというわけで、常に危険に晒されています。
Unityが提供するdllのinternalにアクセスしたいなどの場合に、ぜひ試してみてください。