如何通过反射调用内部静态函数

如何通过反射调用内部静态函数_第1张图片

我们用ILSpy反编译UnityEditor.dll,假设现在我们想要调用UnityEditor.EditorGUIUtility的这个DrawHorizontalSplitter方法,因为它是internal的,科普:

internal(内部)关键字是类型和类型的成员访问修饰符。只有在同一程序集中可访问,可以跨类。

注:ILspy是一个开源的.net反编译软件,使用十分方便,下载地址:https://github.com/icsharpcode/ILSpy/releases

所以我们就无法在外部直接调用DrawHorizontalSplitter这个方法。

但是,我们可以用反射的方式来调用。

我们封装一个反射工具的类:

using UnityEngine;
using System;
using System.Reflection;

public class ReflectionTools
{
    public static void Call(string typeName, string methodName, params object[] args)
    {
        Call(typeName, methodName, args);
    }

    public static T Call(string typeName, string methodName, params object[] args)
    {
        Type type = Type.GetType(typeName);
        T defaultValue = default(T);
        if(null == type) return defaultValue;
        
        Type[] argTypes = new Type[args.Length];
        for(int i=0, count = args.Length; i< count; ++i)
        {
            argTypes[i] = null != args[i] ? args[i].GetType() : null;
        }
        MethodInfo method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, argTypes, null);
        if(null == method)
        {
            Debug.LogError(string.Format("method {0} does not exist!",methodName));
            return defaultValue;
        }
        object result = method.Invoke(null, args);
        if(null == result)
            return defaultValue;
        if(!(result is T))
        {
            Debug.LogError(string.Format("method {0} cast failed!",methodName));
            return defaultValue;
        }
        return (T)result;
    }
}

这样,我们就可以调用了:

ReflectionTools.Call("UnityEditor.EditorGUIUtility, UnityEditor", "DrawHorizontalSplitter", new Rect(0f,0f,100f,100f));

 

同理,假设我们想用EditorStyles的toolbarSearchField属性:

如何通过反射调用内部静态函数_第2张图片

我们先封装工具接口

using UnityEngine;
using System;
using System.Reflection;

public class ReflectionTools
{
    public static T GetProperty(string typeName, string propertyName)
    {
        return GetProperty(null, typeName, propertyName);
    }

    public static T GetProperty(object instance, string typeName, string propertyName)
    {
        bool isStatic = null == instance;
        Type type = Type.GetType(typeName);
        T defaultValue = default(T);
        if(null == type) return defaultValue;
        
        BindingFlags flag = (isStatic ? BindingFlags.Static : BindingFlags.Instance);
        PropertyInfo property = type.GetProperty(propertyName, flag | BindingFlags.Public | BindingFlags.NonPublic);
        if(null == property)
        {
            Debug.LogError(string.Format("property {0} does not exist!",propertyName));
            return defaultValue;
        }
        object result = property.GetValue(instance, null);
        if(null == result)
            return defaultValue;
        if(!(result is T))
        {
            Debug.LogError(string.Format("property {0} cast failed!",propertyName));
            return defaultValue;
        }
        return (T)result;
    }
}

调用:

GUIStyle style = ReflectionTools.GetProperty("UnityEditor.EditorStyles, UnityEditor", "toolbarSearchField");

如果要获取成员变量,可以封装一个GetField方法,原理和GetProperty类似,只需要把type.GetProperty缓存type.GetField即可:

using UnityEngine;
using System;
using System.Reflection;

public class ReflectionTools
{
    public static T GetField(string typeName, string fieldName)
    {
        return GetField(null, typeName, fieldName);
    }

    public static T GetField(object instance, string typeName, string fieldName)
    {
        bool isStatic = null == instance;
        Type type = Type.GetType(typeName);
        T defaultValue = default(T);
        if(null == type) return defaultValue;
        
        BindingFlags flag = (isStatic ? BindingFlags.Static : BindingFlags.Instance);
        FieldInfo field = type.GetField(fieldName, flag | BindingFlags.Public | BindingFlags.NonPublic);
        if(null == field)
        {
            Debug.LogError(string.Format("field {0} does not exist!",fieldName));
            return defaultValue;
        }
        object result = field.GetValue(instance, null);
        if(null == result)
            return defaultValue;
        if(!(result is T))
        {
            Debug.LogError(string.Format("field {0} cast failed!",fieldName));
            return defaultValue;
        }
        return (T)result;
    }
}

 

你可能感兴趣的:(unity3D,C#,Unity3D,反射,c#)