简体   繁体   中英

Why Reflection List<T> is not generic?

I can't understand why my fieldType is not qualified as a generic list. I tried to use the solution proposed below to get the generic type of a list. But when I reach fieldType.IsGenericType == false , I was quite surprised and I don't understand what is happening.

My goal is to be able to use my method CreateTable() for each field in my context. My context should only have List fields.

This is the information i found in my object:

FieldType = {Name = "List`1" FullName = 
"System.Collections.Generic.List`1[[WebApplication1.Models.Movie, WebApplication1,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"}

Reference : C# generic list <T> how to get the type of T?

My code example:

public class MediaContext
{
    public List<Movie> Movies { get; set; }
    public List<Subtitle> Subtitles { get; set; }

    public MediaContext()
    {
        this.Movies = new List<Movie>();
        this.Subtitles = new List<Subtitle>();
    }
}


public void CreateDB(object context)
{
    Type type = context.GetType();
    FieldInfo[] fields = type.GetFields(BindingFlags.Instance 
        | BindingFlags.NonPublic);

    foreach (FieldInfo field in fields)
    {
        Type genericType = this.GetGenericType(field);

        MethodInfo method = this.GetType().GetMethod("CreateTable");
        MethodInfo generic = method.MakeGenericMethod(genericType);
        generic.Invoke(this, null);
    }

    foreach (FieldInfo field in fields)
    {
        Type genericType = this.GetGenericType(field);

        MethodInfo method = this.GetType().GetMethod("AddKeys");
        MethodInfo generic = method.MakeGenericMethod(genericType);
        generic.Invoke(this, null);
    }
}

private Type GetGenericType(FieldInfo field)
{
    Type fieldType = field.GetType();
    Type genericType = null;
    // Where I believe is should be generic.
    if (fieldType.IsGenericType && 
        fieldType.GetGenericTypeDefinition() == typeof(List<>))
    {
        genericType = fieldType.GetGenericArguments()[0];
    }
    else
    {
        throw new Exception("An array is needed");
    }

    return genericType;
}

public void CreateTable<T>()
{
    StringBuilder query = new StringBuilder();
    Type type = typeof(T);

    query.Append(String.Format("CREATE TABLE {0} (", NamingGeneration.PlurializeName(type.Name)));

    query.Append(this.AddFields(typeof(T).GetProperties()));

    query.Append(")");

    SqlCommand command = new SqlCommand();

    command.CommandText = query.ToString();

    SqlExecuteRequest.Instance.ExecuteNonQuery(command);
}

private void AddKeys<T>()
{
    Type type = typeof(T);
    PropertyInfo[] properties = type.GetProperties();

    IEnumerable<PropertyInfo> keyedProperties = properties.Where(x => x.Name.Contains("Id"));

    foreach (PropertyInfo property in keyedProperties)
    {
        if (property.Name == "Id")
        {
            this.AddPrimaryKey(type.Name, property.Name);
        }
        else if (property.Name.EndsWith("Id"))
        {
            this.AddForeignKey(type.Name, property.Name);
        }
    }
}

To fix the code as you have it, instead of

   Type fieldType = field.GetType();

You want

Type fieldType = field.FieldType;

And it will work. FieldInfo is what you pass through. When you call GetType(), the type you're getting is the FieldInfo type information. FieldInfo contains information about a Field, and the Type information is held in FieldInfo.FieldType.

If you step through this code, you would see this behavior. Debugging is useful.

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