- Home /
Reflection only works in Play Mode?
Hi guys I'm trying to get some types here but the code aways return null inside my Editor Window but if I use the same piece of code on a monobehaviour while playing in unity the code just works. Any word on that?
The code:
System.Type t = System.Type.GetType("NSNode")
Debug.Log(t);
t is aways null while in the editor, and aways NSNode inside the 'game'.
Here is the full code with the Instancing method I'm trying to use:
System.Type t = System.Type.GetType("NSNode")
Debug.Log(t);
NSNode n = (NSNode)System.Activator.CreateInstance(t);
Debug.Log(n);
Why not just use System.Type t = typeof(NSNode);
ins$$anonymous$$d? On that subject, why not just instantiate the class in the usual way with new NSNode();
? Editor scripts can access and use classes, structs, enums, etc from runtime scripts.
The reason that Type.GetType
is not working likely means that you need to use the assembly qualified type name ins$$anonymous$$d.
It's just an example, I actually don't know the type of class that will come, but they will all derive from NSNode through inheritance.
In that case you should be using assembly qualified names, then System.Type.GetType
will return the correct type (provided that the assembly is in fact loaded!)
That "provided that the assembly is loaded" is my worst fear! How can I get the qualified with just a string?
Okay, so in that case the assembly will be loaded and accessible by editor scripts. I do a similar thing with my scripts and experience no issues whatsoever. Try using System.Type.GetType("NSNode,Assembly-CSharp")
and let me know how that goes.
Answer by numberkruncher · Feb 17, 2013 at 10:13 PM
To access information for a specific type that is in a different assembly you have two choices:
Choice #1 - Use an assembly qualified name
This can be achieved with and without namespaces:
// Without a namespace
System.Type nodeType = System.Type.GetType("NSNode,Assembly-CSharp");
// With a namespace
System.Type nodeType = System.Type.GetType("Some.Namespace.NSNode,Assembly-CSharp");
As one might guess, the runtime assembly for UnityScripts is "Assembly-UnityScript".
Choice #2 - Get access to the assembly through a known class
Let's suppose that you have a class called "SomeRuntimeClass" which exists in the runtime assembly. You can then access any other types in that assembly without needing assembly qualified lookups:
// Start of script, keep local copy of assembly
private Assembly runtimeAssembly = typeof(SomeRuntimeClass).Assembly;
// OR
private Assembly runtimeAssembly = Assembly.Load("Assembly-CSharp");
...
// Lookup class from assembly by name alone:
System.Type nodeType = runtimeAssembly.GetType("NSNode");
And then use the Activator
class to create an instance of nodeType
.
@Lea is there a way to instantiate from a string from another assembly without knowing the qualified name? I mean, having just the name "ClassX" is possible to find the the qualified name? I don't think so but a pro must confirm.
If you know which assembly then you can just use the second option above where you only need to specify the name "ClassX". If the assembly is unknown then you can enumerate all assemblies to search for the type, though this is relatively slow (so you might need to cache lookups to improve performance using a Dictionary). Also you run the risk at instantiating objects that you don't know about...
For best performance you need one known, be it an assembly qualified type name, or a reference to the assembly.
Have you considered using an object factory and creator design pattern ins$$anonymous$$d of reflection? When one turns to reflection it is usually because there was no other better solution. If possible reflection should be avoided because it is like black magic.
A quite similar question has been asked just yesterday.
Just read the docs on GetType carefully. The string parameter description explains everything. You need an assembly qualified type string if the class you want to access is not part of the current assembly or the mscorelib. I've posted an extension method on the other question which will return a list of all classes which are derived from the given type.
So in your case something like that:
var types = typeof(NSNode).GetAllDerivedClasses();
This will list all classes from all loaded assemblies which are derived from NSNode.