Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic Type as a Variable

Tags:

c#

I have a Method which accepts a Generic T class

  public void CreateTables<T>()
   {
    string name = typeof(T).Name;

    var fields = typeof(T).GetProperties().Select(t => new { key = 
    t.Name.ToLower(CultureInfo.InvariantCulture), value = 
    SqLiteUtility.GetSQLiteTypeString(t.PropertyType) })
      .ToDictionary(t => t.key, t => 
          t.value);

    CreateTable(name, fields);
    }

   and 

    public void PushData<T>() where T : EntityData
   {
    var data = _context.Set<T>().Where(p => p.Deleted == false).ToList();
   }

I have more than 50 types for which this method needs to be called Like this

CreateTables<Class1>();
PushData<Class1>();

Although I can do like this, but i prefer to create maybe array of Types and use for loop to call this method

Something like this

   Type[] types=new Types[]{typeof(Class1),typeof(Class2)}

   foreach(var type in types)
   {
    //call create table method
      CreateTables<type>(); - - this doesnt work as "type" is a variable 
                                used as a type 

   }

Is there a way around this? that can also save me a lot of code and refactor things effectively?

EDIT1:

From the answers , indeed Parameters like CreateTables(Type T) can work, however for the second method above, is there also a possibility?

In the second it's important that T is mentioned of type EntityData as the code in the method depends on it.

like image 272
Mandar Jogalekar Avatar asked Nov 09 '17 12:11

Mandar Jogalekar


1 Answers

Essentially you're trying to go from reflection to generics and back to reflection.

Since the method in question simply steps back into reflection a better method is to create an overload taking a type, like this:

public void CreateTables<T>()
{
    CreateTables(typeof(T));
}

public void CreateTables(Type tableType)
{
    string name = tableType.Name;

    var fields = tableType.GetProperties().Select(t => new
        {
            key = t.Name.ToLower(CultureInfo.InvariantCulture),
            value = SqLiteUtility.GetSQLiteTypeString(t.PropertyType)
        })
        .ToDictionary(
            t => t.key,
            t => t.value);

    CreateTable(name, fields);
}

This way you can still call it with a specific type, generics-wise, or you can call it from your loop by simply passing the type object.


Having said all that, if you cannot change the method to take a Type object, here's how you need to invoke it using reflection:

var m = GetType().GetMethod("CreateTables").MakeGenericMethod(new Type[] { type });
m.Invoke(this, null);

Note! This assumes you only have one such method available, that it is public, etc.

like image 198
Lasse V. Karlsen Avatar answered Oct 03 '22 00:10

Lasse V. Karlsen