はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Unity, C#】InternalsVisibleToを用いて特定アセンブリからinternalにアクセスできるようにする

はじめに

今回はInternalsVisibleToという属性(Attribute)について紹介したいと思います。

同一アセンブリ内でないとアクセスできない

皆さんご存知かと思いますが、internalを利用することで同一アセンブリでしかアクセスできないようにすることができます。

internal 型またはメンバーは、次の例のように、同じアセンブリ内のファイルでのみアクセスできます。

internal - C# リファレンス | Microsoft Docs


UnityではAssembly Definition Filesを利用するとアセンブリを分けることができる訳ですが、特にテスト周りでinternalにもアクセスしたくなることが多々あるかと思います。
アセンブリの定義 - Unity マニュアル

それを可能にするのが今回紹介するInternalsVisibleToになります。

InternalsVisibleTo

通常は現在のアセンブリ内でのみ参照できる型が、指定したアセンブリから参照可能であることを指定します。

InternalsVisibleToAttribute クラス (System.Runtime.CompilerServices) | Microsoft Docs

[System.AttributeUsage(System.AttributeTargets.Assembly, AllowMultiple=true, Inherited=false)]
public sealed class InternalsVisibleToAttribute : Attribute


使い方は簡単で、ファイルの冒頭に以下のようなコードを書けばOKです。

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Tests")]

こうすることで引数に記述したアセンブリは、InternalsVisibleToを記載したアセンブリの全てのinternalにアクセス可になります。

一つ注意点なのは、InternalsVisibleTo使われる側のアセンブリに記述するということですね。

InternalsVisibleToは使われる側に記述

たまに私も逆だったけと戸惑うことがあったりなかったり。

Unity公式の使用例

Unityの実装ではAssemblyInfo.csというファイルが用意され、中にInternalsVisibleToを列挙しているようです。

// Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License

using System.Runtime.CompilerServices;
using UnityEngine;

// ADD_NEW_PLATFORM_HERE
[assembly: InternalsVisibleTo("Unity.LiveNotes")]
[assembly: InternalsVisibleTo("Unity.Burst")]
[assembly: InternalsVisibleTo("Unity.Burst.Editor")]
[assembly: InternalsVisibleTo("Unity.Cloud.Collaborate.Editor")]
[assembly: InternalsVisibleTo("Unity.CollabProxy.Editor")]
[assembly: InternalsVisibleTo("Unity.CollabProxy.EditorTests")]
[assembly: InternalsVisibleTo("Unity.CollabProxy.UI")]
[assembly: InternalsVisibleTo("Unity.CollabProxy.UI.Tests")]
[assembly: InternalsVisibleTo("Unity.CollabProxy.Client")]
[assembly: InternalsVisibleTo("Unity.CollabProxy.Client.Tests")]
// 以下省略

UnityCsReference/AssemblyInfo.cs at master · Unity-Technologies/UnityCsReference · GitHub

またアセンブリを見ても、だいたいEditorTests周りっぽいですね。

使用例

InternalsVisibleToは対象アセンブリ内であればどこに書いてもよいのですが、AssemblyInfo.csを用意するのが割と主なんですかね?

断言できませんが、割と見る気はします。

また実装する際InternalsVisibleToの引数の文字列は、Assembly Definition Filesに記述したNameと一致させてあげればOKです。

using System.Runtime.CompilerServices;
using UnityEngine;

[assembly: InternalsVisibleTo("Tests")]
asmdefのNameと一致させる