Alex
Alex

Reputation: 397

Determining if a field is using a generic parameter

I've been baffled by this and can't seem to get my head around it so hopefully someone can point me in the right direction.

I have a class as follows:

public class Foo<T>
{
    public List<T> Data;
}

Now I'm writing code to reflect this class and want to work out a way of determining that the field Data has a generic parameter being used.

My initial approach was to continue going down as many levels as I could and once I hit the IsGenericParameter field set to true I would rather than reflect the type name instead place a "Generic Argument" string there, however I can't seem to get this to work the way I want it to.

I've looked around but every solution I've found seems to point to a dead end with this at the moment.

Upvotes: 3

Views: 94

Answers (2)

D Stanley
D Stanley

Reputation: 152634

You want IsGenericType, not IsGenericParameter:

bool isGeneric = typeof(Foo<int>).GetField("Data").FieldType.IsGenericType;

If you want to know of the parameter for the List is generic, then you have to look one more level down:

bool isGeneric = typeof(Foo<>).GetField("Data")
                                 .FieldType
                                 .GetGenericArguments()[0] // only generic argument to List<T>
                                 .IsGenericParameter;

what if Data field was a Dictionary with Dictionary<string, T>. How would I determine which type was using a generic parameter?

Call GetGenericArguments on the type and look at each type in the resulting array

public class Foo<T>
{
    public Dictionary<string, T> Bar;
}

Type[] types = typeof(Foo<>).GetField("Bar").FieldType.GetGenericArguments();

Console.WriteLine("{0}\n{1}",
    types[0].IsGenericParameter,  // false, type is string
    types[1].IsGenericParameter   // true,  type is T
);

Basically, IsGenericParameter is used when looking at the generic parameters of a type to see if it is generic or if is has a type sepcified.

Upvotes: 3

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727047

Here is how to distinguish generic types that rely on class type parameter from generic types that do not. Consider this example:

class Foo<T> {
    public List<T> field1;   // You want this field
    public List<int> field2; // not this field
}

Start by getting generic type definition, and pulling its type arguments:

var g = typeof(Foo<string>).GetGenericTypeDefinition();
var a = g.GetGenericArguments();

This will give you an array with a single type that represents generic type parameter T. Now you can go through all fields, and search for that type among generic type arguments of field types, like this:

foreach (var f in g.GetFields()) {
    var ft = f.FieldType;
    if (!ft.IsGenericType) continue;
    var da = ft.GetGenericArguments();
    if (da.Any(xt => a.Contains(xt))) {
        Console.WriteLine("Field {0} uses generic type parameter", f.Name);
    } else {
        Console.WriteLine("Field {0} does not use generic type parameter", f.Name);
    }
}

This code produces the following output:

Field field1 uses generic type parameter
Field field2 does not use generic type parameter

Upvotes: 1

Related Questions