简体   繁体   中英

Determine whether field is of generic type or not

Is it possible to determine via reflection whether a field is of generic type or not?

If it is possible, how can it be done?

I suppose my question was not clear enough so I am editing it now.

EDIT:

If a would have a type defined as in following example and DID NOT have instance of Holder<T> type, but only System.Type instance retrieved via System.Reflection.Assembly.GetTypes and System.Reflection.FieldInfo instance describing field _instance, how can I determine whether _instance field is of generic type

public class Holder<T>
{
   private T _instance;
}

Using the FieldInfo for the field, you can check the IsGenericType property of the FieldType property if you want to know if the field is a generic type in itself.

 var info = type.GetField("myField",BindingFlags.Private);
 if (info != null)
 {
      if (info.FieldType.IsGenericType)
      {
           Console.WriteLine( "The type of the field is generic" );
      }
 }

If you what to check if the field is of the type of the generic in a generic class definition, then you'll want to check IsGenericParameter instead.

 var info = type.GetField("myField",BindingFlags.Private);
 if (info != null)
 {
      if (info.FieldType.IsGenericParameter)
      {
           Console.WriteLine( "The type of the field is the generic parameter of the class" );
      }
 }

You can, of course, combine these. Checking if the field is a generic of the type in a generically defined class, is more problematic, but still can be done. You simply have to check the type parameters of the generic type to see if one of them has IsGenericParameter set. Note the following example is only one level deep; if you want something comprehensive you'll want to define a method and use it recursively.

var info = type.GetField("myField",BindingFlags.Private);
if (info != null)
{
     if (info.FieldType.IsGenericType)
     {
         foreach (var subType in info.FieldType.GetGenericArguments())
         {
             if (subType.IsGenericParameter)
             {
                 Console.WriteLine( "The type of the field is generic" );
             }
         }
     }
}

Try out

field.GetType().IsGenericType

Type.IsGenericType Property :

Gets a value indicating whether the current type is a generic type.

Let me rephrase your question the way I understand it:

I have a generic type and I want to find out whether a certain field type contains (one of) the type argument. How do I do that?

If you want to find out whether a certain type is a generic parameter, you can use the IsGenericParameter property . That returns true for T , but not for List<T> . If you want that, you have use recursion:

bool ContainsGenericParameter(Type fieldType)
{
    return fieldType.IsGenericParameter ||
        fieldType.GetGenericArguments().Any(t => ContainsGenericParameter(t));
}

For example, if you have a type like this:

public class Holder<T>
{
   private T _t;
   private int _int;
   private List<T> _listT;
   private List<int> _listInt;
}

This query

typeof(Holder<>)
    .GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
    .Select(f => new { f.Name, Generic = ContainsGenericParameter(f.FieldType) })

Will return something like this:

Name     Generic
_t       True
_int     False
_listT   True
_listInt False

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM