- Home /
Anyone know how to get Type.GetMethods( ...) to return private methods?
Hi,
I need to get a list of all instance methods available an object via the reflection system so I do the following:
Type tidObject = SomeObject.GetType();
MethodInfo[] aminfo = tidObject.GetMethods( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance );
Debug.Log( "################### METHODS FOR - " + tidObject.Name );
foreach( MethodInfo minf in aminfo )
{
string strParamList = "()";
ParameterInfo[] apinfo = minf.GetParameters();
if( 0 < apinfo.Length )
{
strParamList = "( ";
foreach( ParameterInfo pinfo in apinfo )
{
strParamList += pinfo.ParameterType.Name + ", ";
}
strParamList += ")";
}
Debug.Log( "function :" + minf.Name + strParamList );
}
In the current version of Unity (4.50.0f6) this prints out the name and parameter list of all public and protected methods of SomeObject - but no private methods.
The documentation for C# on MSDN specifies that this combination of BindingFlags values should also return private methods.
Can anyone confirm whether this is expected behaviour in Unity?
(e.g. are private methods disabled in the reflection system for some reason?)
Cheers,
Alex
Do you have a simple sample class which reproduces this behaviour which you can share?
Answer by Bunny83 · Jun 04, 2014 at 10:29 PM
If i use exactly your code in Start on the MonoBehaviour itself (this.GetType()) i see all methods, even "Start" which is private as well.
The output looks like that:
################### METHODS FOR - App
function :Start()
function :OnDisable()
function :OnGUI()
function :Invoke( String, Single, )
function :InvokeRepeating( String, Single, Single, )
function :CancelInvoke()
function :CancelInvoke( String, )
function :IsInvoking( String, )
function :IsInvoking()
function :StartCoroutine( IEnumerator, )
function :StartCoroutine_Auto( IEnumerator, )
function :StartCoroutine( String, Object, )
function :StartCoroutine( String, )
function :StopCoroutine( String, )
function :StopAllCoroutines()
function :get_useGUILayout()
function :set_useGUILayout( Boolean, )
function :get_enabled()
function :set_enabled( Boolean, )
function :get_transform()
function :InternalGetTransform()
function :get_rigidbody()
function :get_rigidbody2D()
function :get_camera()
function :get_light()
function :get_animation()
function :get_constantForce()
function :get_renderer()
function :get_audio()
function :get_guiText()
function :get_networkView()
function :get_guiElement()
function :get_guiTexture()
function :get_collider()
function :get_collider2D()
function :get_hingeJoint()
function :get_particleEmitter()
function :get_particleSystem()
function :get_gameObject()
function :InternalGetGameObject()
function :GetComponent( Type, )
function :GetComponent()
function :GetComponent( String, )
function :GetComponentInChildren( Type, )
function :GetComponentInChildren()
function :GetComponentsInChildren( Type, )
function :GetComponentsInChildren( Type, Boolean, )
function :GetComponentsInChildren( Boolean, )
function :GetComponentsInChildren()
function :GetComponents( Type, )
function :GetComponents()
function :get_active()
function :set_active( Boolean, )
function :get_tag()
function :set_tag( String, )
function :CompareTag( String, )
function :SendMessageUpwards( String, Object, SendMessageOptions, )
function :SendMessageUpwards( String, Object, )
function :SendMessageUpwards( String, )
function :SendMessageUpwards( String, SendMessageOptions, )
function :SendMessage( String, Object, SendMessageOptions, )
function :SendMessage( String, Object, )
function :SendMessage( String, )
function :SendMessage( String, SendMessageOptions, )
function :BroadcastMessage( String, Object, SendMessageOptions, )
function :BroadcastMessage( String, Object, )
function :BroadcastMessage( String, )
function :BroadcastMessage( String, SendMessageOptions, )
function :Equals( Object, )
function :GetHashCode()
function :GetInstanceID()
function :get_name()
function :set_name( String, )
function :get_hideFlags()
function :set_hideFlags( HideFlags, )
function :ToString()
function :Finalize()
function :GetType()
function :MemberwiseClone()
function :obj_address()
ps: My project is an Android project, but switching to Webplayer works as well.
I'm not sure what you're missing in your case, but it shows all methods.
Riiiiiight - thanks for the sanity check :)
I have discovered the problem - user error (unsurprisingly)!
Private methods of base classes don't show up.
Obviously this makes sense, since private methods aren't accessible to derived types & so don't belong in the method list of the derived types...
The reason this tripped me up is (I think) "Quite Interesting" :)
I have a very specific situation that caused my confusion - essentially as follows:
class A : $$anonymous$$onoBehaviour
{
// DelegatedEvent is a custom serialisable type for an custom event system
[PropertyDrawerAttributeForDelegatedEvent( "NameOfDelegate" )]
public DelegatedEvent m_OnEventReceivedCallDelegate;
private void NameOfDelegate()
{
// do stuff when event received
}
}
class B : class A
{
// extends class A in various ways
}
The property drawer for DelegatedEvent uses the name of the method specified in the PropertyDrawerAttributeForDelegatedEvent to correctly set the state of m_OnEventReceivedCallDelegate so that it can find the method using C#'s reflection system, create a delegate to it, and invoke the delegate when a specific event occurs (events are identified by strings specified via the property drawer).
The property drawer that is used to draw the DelegatedEvent in the Unity Editor GUI expects to be able to find the method in the reflection data of the class which the serialised property it's editing is part of.
This works fine when class A is attached as a component to a GameObject, because the function NameOfDelegate appears in the array generated by A.Get$$anonymous$$ethods( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance )
However, it fails miserably when class B is attached to a GameObject because the function NameOfDelegate doesn't appear in tha array generated by B.Get$$anonymous$$ethods( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance )
Whilst I could work around this by iterating the methods of base classes too I think the simplest thing for me to do here is just accept that any methods I use with the delegated event should be protected or public and put a check into the property drawer to warn the user - e.g.
Debug.LogError( "Failed to find method " + str$$anonymous$$ethodNameSpecifiedByAttribute + " - check it's not 'private' - methods used as delegates this system should be public or protected" );
Anyway, I hope this wasn't uninteresting and thanks for your help!
$$anonymous$$
Yes, right, private members(fields, properties, methods, ...) of parent classes don't belong to the child class at all, that's why they are private ;). To get all methods you would use the bindflags above on the instance and only "private, instance" on all parent classes.
Anyways, reflection shouldn't be the "normal" way to access methods.
..of course it's not the normal way to access methods! :)
It's anything but normal - I expect that only a handful of people have ever - or will ever - come into contact with this reflection / access / inheritance hierarchy / GUI rendering edge-case ;)
The reason I'm using reflection is so that I can use a bunch of Unity Editor GUI extensions to allow behaviour to be created in the Editor that would normally have to be scripted by hand - essentially, a simpler and more programmer centric version of the visual scripting solutions like playmaker.
Thanks again for your help.
$$anonymous$$
Your answer
Follow this Question
Related Questions
In-Game Console and Permanent Variable Changes 1 Answer
SendMessage vs MethodInfo.Invoke 1 Answer
Reflection property 1 Answer
The problem with the beam reflected from the object. 1 Answer
How to echange a script of a component? 2 Answers