I’ve searched for generic classes and found out about instantiating generic classes but I haven’t been able to find an answer to what I’m looking for. Hopefully someone more skilled can shed some light at how to perform this.
Question:
What I want to do is 1) add a component of a generic type and then 2) call a method in that component that I know exists in a parent class of that component.
Pseudo Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Manager.cs
public class ManagerClass : MonoBehaviour
{
void Awake()
{
GameObject _g = new GameObject();
// The string "DerivedClass2" could be any string which I don't know at this point - the example uses DerivedClass2 as an example.
System.Type _anyDerivedClass = System.Type.GetType("DerivedClass2");
// BEGIN QUESTION This is what I want to do - pseudo code which doesn't work :)
_anyDerivedClass.GetType() _c = _g.AddComponent(_anyDerivedClass);
_c.Import();
// END QUESTION
}
}
// BaseClass.cs
public class BaseClass : MonoBehaviour
{
public virtual void Import()
{
// Perform import here
}
}
// DerivedClass1.cs
public class DerivedClass1 : BaseClass
{
}
// DerivedClass2.cs
public class DerivedClass2 : BaseClass
{
}
The virtual method will exist in the derived class. That’s not an example of anything “generic”, though.
You’re already using the type in your GetType(“Name Here”) portion of code, I don’t see why you wouldn’t just do:
Thanks, for your reply. I would like to keep the code generic because in the Manager, the same method should be able to add component of N number of derived classes and call the Import method of that class (that exists in the parent). Also, a JSON string will contain the name of the class as a string which is why I don’t know the actual class. I can work around the problem without generic code using if statements to find class and cast it, e.g.:
if (_anyDerivedClass == typeof(DerivedClass1))
((DerivedClass1) _anyDerivedClass).Import();
if (_anyDerivedClass == typeof(DerivedClass2))
((DerivedClass2) _anyDerivedClass).Import();
…but it wouldn’t be pretty nor would it scale well.
If you can guarantee that the instantiated component is a child of your base class then you can type cast it. You can use Type.IsSubclassOf to do the first part of that.
I see - now I understand the reason for the string. I believe you should use the type after you got it from the string version of GetType() (ie: not use “.GetType()” again on the next line).
Thanks Dave-Carlile, it’s a guarantee to be a subclass so “IsSubclassOf” did the trick.
For reference, this is an updated pseudo version:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Manager.cs
public class ManagerClass : MonoBehaviour
{
void Awake()
{
GameObject _g = new GameObject();
// The string "DerivedClass2" could be any string which I don't know at this point - the example uses DerivedClass2 as an example.
System.Type _anyDerivedClass = System.Type.GetType("DerivedClass2");
// SOLUTION (thank Dave-Carlile)
if (_anyDerivedClass.IsSubclassOf(typeof(_anyDerivedClass))
{
BaseClass _c = (BaseClass) _g.AddComponent(_anyDerivedClass);
_c.Import();
}
// END SOLUTION
}
}
// BaseClass.cs
public class BaseClass : MonoBehaviour
{
public virtual void Import()
{
// Perform import here
}
}
// DerivedClass1.cs
public class DerivedClass1 : BaseClass
{
}
// DerivedClass2.cs
public class DerivedClass2 : BaseClass
{
}
In my project the actual code segment looks like this (I’m using SimpleJSON) and when I loop through a string containing multiple blueprints it’ll instantiate a new GameObject, add the appropriate blueprint component, and import the actual configuration of that blueprint from the subsection of JSON.
// Parse the JSON string
var N = JSON.Parse(_str);
int _i = 0;
while (N["item" + _i] != null)
{
GameObject _go = new GameObject();
System.Type _blueprintClass = System.Type.GetType("ProceduralPlanets." + N["item" + _i]["type"]);
if (_blueprintClass.IsSubclassOf(typeof(BlueprintPlanet)))
{
BlueprintPlanet _c = (BlueprintPlanet)_go.AddComponent(_blueprintClass);
_c.ImportFromJSON(N["item" + _i].ToString());
}
_i++;
}