コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】static な event の登録数を取得する方法

概要

using System;
using System.Reflection;

public static class DelegateExt
{
    public static int GetLength<T>( string name )
    {
        return GetLength( typeof( T ), name );
    }

    public static int GetLength( this Type self, string name )
    {
        var attrs =
            BindingFlags.GetField   |
            BindingFlags.Static     |
            BindingFlags.NonPublic  |
            BindingFlags.Public
        ;
        var field = self.GetField( name, attrs );
        if ( field == null )
        {
            throw new ArgumentException( $"name is invalid parameter: {name}" );
        }
        var d = field.GetValue( null ) as Delegate;
        if ( d == null ) return 0;
        var list = d.GetInvocationList();
        if ( list == null ) return 0;
        var length = list.Length;
        return length;
    }
}

上記のような関数を定義して

using UnityEngine;

public class Example : MonoBehaviour
{
    private void Awake()
    {
        var t = typeof( Application );

        Application.focusChanged                += Application_focusChanged         ;
        Application.lowMemory                   += Application_lowMemory            ;
        Application.lowMemory                   += Application_lowMemory            ;
        Application.logMessageReceived          += Application_logMessageReceived   ;
        Application.logMessageReceived          += Application_logMessageReceived   ;
        Application.logMessageReceived          += Application_logMessageReceived   ;
        Application.logMessageReceivedThreaded  += Application_logMessageReceived   ;
        Application.logMessageReceivedThreaded  += Application_logMessageReceived   ;
        Application.logMessageReceivedThreaded  += Application_logMessageReceived   ;
        Application.logMessageReceivedThreaded  += Application_logMessageReceived   ;
        Application.quitting                    += Application_quitting             ;
        Application.quitting                    += Application_quitting             ;
        Application.quitting                    += Application_quitting             ;
        Application.quitting                    += Application_quitting             ;
        Application.quitting                    += Application_quitting             ;

        Debug.Log( t.GetLength( "focusChanged"                  ) );
        Debug.Log( t.GetLength( "lowMemory"                     ) );
        Debug.Log( t.GetLength( "s_LogCallbackHandler"          ) );
        Debug.Log( t.GetLength( "s_LogCallbackHandlerThreaded"  ) );
        Debug.Log( t.GetLength( "quitting"                      ) );
    }

    private void Application_focusChanged( bool obj ) { }
    private void Application_lowMemory() { }
    private void Application_logMessageReceived( string condition, string stackTrace, LogType type ) { }
    private void Application_quitting() { }

    private void OnDestroy()
    {
        Application.focusChanged                -= Application_focusChanged         ;
        Application.lowMemory                   -= Application_lowMemory            ;
        Application.lowMemory                   -= Application_lowMemory            ;
        Application.logMessageReceived          -= Application_logMessageReceived   ;
        Application.logMessageReceived          -= Application_logMessageReceived   ;
        Application.logMessageReceived          -= Application_logMessageReceived   ;
        Application.logMessageReceivedThreaded  -= Application_logMessageReceived   ;
        Application.logMessageReceivedThreaded  -= Application_logMessageReceived   ;
        Application.logMessageReceivedThreaded  -= Application_logMessageReceived   ;
        Application.logMessageReceivedThreaded  -= Application_logMessageReceived   ;
        Application.quitting                    -= Application_quitting             ;
        Application.quitting                    -= Application_quitting             ;
        Application.quitting                    -= Application_quitting             ;
        Application.quitting                    -= Application_quitting             ;
        Application.quitting                    -= Application_quitting             ;
    }
}

このようなコードを記述することで

f:id:baba_s:20190331124821p:plain

static な event の登録数を取得できます

注意

例えば Application.logMessageReceived や Application.logMessageReceivedThreaded は
内部における名前は s_LogCallbackHandler や s_LogCallbackHandlerThreaded なので、
DelegateExt.GetLength に指定する名前を間違えないようにする必要があります

using System.Reflection;
using System.Text;
using UnityEngine;

public class Example : MonoBehaviour
{
    private void Awake()
    {
        var attrs =
            BindingFlags.GetField   |
            BindingFlags.Static     |
            BindingFlags.NonPublic  |
            BindingFlags.Public
        ;

        var t       = typeof( Application );
        var fields  = t.GetFields( attrs );
        var sb      = new StringBuilder();
        foreach ( var n in fields )
        {
            sb.AppendLine( n.Name );
        }
        Debug.Log( sb.ToString() );
    }
}

内部における名前は上記のようにリフレクションを使用することで

lowMemory
s_LogCallbackHandler
s_LogCallbackHandlerThreaded
OnAdvertisingIdentifierCallback
focusChanged
wantsToQuit
quitting
s_RegisterLogCallbackDeprecated

このように取得することができます

参考サイト様

関連記事