はじめに
今回はコンパイル後の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
にアクセスしたいなどの場合に、ぜひ試してみてください。