I have class derived from a generic type like this:
class MyGeneric<T> {...}
class MyDerivedString : MYGeneric<string> {...}
At runtime, my code reads information to create a string
derivate of MyGeneric
from a file. So I have the name of the generic to instatiate (here: “MyGeneric”) and the name of the class to instantiate it with (in this case “string”).
The file I am reading not only contains text to tell my code to create “string” instances of “MyGeneric”, but also other instances, like “int”, “float” or “boolean”, where there are no derived classes (like “MyDerivedFloat”, etc).
Currently, I create an instance of the generic using the following code:
//all typenames are abbreviated here for clarity, actually they contain the Namespace, like "System.String"
string nameOfGeneric = "MyGeneric"; //this comes from the file
string nameOfType = "string"; //this also comes from the file
Type generic = Type.GetType(nameOfGeneric);
Type typeToUse = Type.GetType(nameofType);
Type typeToInstantiate = generic.MakeGenericType(typeToUse)
var instance = Activator.CreateInstance(typeToInstantiate);
Here comes the problem:
In case the file wants me to instantiate “MyGeneric” with “string”, and we have a class derived from MyGeneric<string>
(like MyDerivedString
, above), we should create an instance of MyDerived
, because it contains additional functions that will have to be used later on.
How can I find the MyDerivedString
Type in the current assembly?
Ok, here comes my first self-answered question.
I actually googled the title of my question and went through the results. The first time none of the title (as seen in google) seemed to answer my question.
Which made me start this question. After typing it all down and going through (very nicely designed, thank you SO) the steps of posting a question, I really read the links on google in SO.
Somewhere was an answer how to get all types of an assembly.
Then lots of answers trying to find stuff related to interfaces.
Aftern going through the codes samples found, I actually tried some code snippets out and came down to this:
public static Type[] GetDerivedTypes(Type generic, Type parameterClass)
{
var instance = generic.MakeGenericType(parameterClass);//derive the instance type from content
var asm = Assembly.GetAssembly(typeof(MyToolsClass));//grab the assembly of a type we know exists
var types = asm.GetTypes().Where(t => t.IsSubclassOf(instance)).ToArray();//get all derived types
return types;
}
So after the calling code turns the text of the file to the Types of the generic class and the instance parameter class, I am scanning all Types defined in the current assembly (beware of types that are from assemblies not currently loaded :), and return all that are subclasses of the requested implementation of the template.
I just check if they are a subclass of the instantiated generic type and return them as an array of Types.
This function now is stashed in an existing static tools class (MYToolsClass
, which I use to get the assembly) and the calling code takes care of making sure we handle not finding an instance type or more than one.
Thank you, StackOverflow, for making me think about the results 🙂
PS:
If anyone has some good suggestions about scanning all assemblies of the running process for the requested types, please let me know.
PPS:
The “Review questions already on Stack Overflow” Step below contains most of the answers I used to come to this solution. I hereby openly admit that I clicked “None of the above”. I spent so much time on this issue (and expanding this post while doing it), that I just hope this will help somebody else along.