Is it possible to get all types that are used as generic type arguments within certain assembly?
Basically, imagine I have this class:
public class Foo<T>
{
T SomeProperty {get; set;}
}
Now, I have an application and there I use the above in some way:
var stringFoo = new Foo<string>();
var intFoo = new Foo<int>();
Assume this is the only place the Foo
is used. Now I would like to get type definitions of Foo<string>
and Foo<int>
. Ie I want to find all types that are constructed from generic type definition ( Foo<T>
) within given assembly.
Is that even possible?
Correction... Still a pain... But no extra libraries needed. Now... On top of my head there are various places where you could find a type Foo<>
:
attributes ( [MyAttribute(typeof(Foo<>)]
, or perhaps Foo<>
is in itself an Attribute
)
base type chain ( class MyClass : Foo<int>
) or if Foo<>
is a IFoo<>
then implemented interfaces
members of a type (fields, properties, events, methods) (here I mean only the signature part of those, so the field type, the method arguments and return type...)
inner types of a type (types defined inside another type)
All of these can be found with "simple" application of reflection.
On top of these you can take a look at local variables of methods/properties (they are methods in the end), events (even they are methods in the end): if you have a MethodInfo method
, you can get a MethodBody body = method.GetMethodBody()
, and the MethodBody
defines a LocalVariables
.
Note that without disassembling the code (for example with Mono.Cecil ) you won't be able to detect that in
public class C
{
public List<int> MyList;
public void M()
{
MyList = new List<int>();
Console.WriteLine(new List<int>());
}
}
the method M
uses a List<int>()
, because no local variable of type List<int>
is used. So in the end you'll need to even disassemble all the methods.
Clearly each time you find a type, you must check if the type is a Foo<>
, a subclass of Foo<>
, or perhaps uses Foo<>
as a parameter ( List<Foo<>>
), or is a pointer Foo<>*
, or a managed pointer ref Foo<>
or...)
As far as variables is concerned, you could discover the types by examining the method.
public static void GetGenericVariables()
{
//Declaring two variables here that use Foo<>
var inttype = new Foo<int>();
var stringType = new Foo<string>();
var methodInfo = typeof(ClassContainingMethod).GetMethod("GetGenericVariables");
var variables = methodInfo.GetMethodBody().LocalVariables;
foreach (var variable in variables)
{
if (variable.LocalType.IsGenericType && variable.LocalType.GetGenericTypeDefinition() == typeof(Foo<>))
{
Console.WriteLine(variable.LocalType.GenericTypeArguments[0].FullName);
}
}
}
Output:
System.Int32
System.String
You would have to recurse over the assemblies and types though.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.