Mandar Jogalekar
Mandar Jogalekar

Reputation: 3281

Generic Type as a Variable

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.

Upvotes: 5

Views: 599

Answers (3)

Roman Koliada
Roman Koliada

Reputation: 5082

Try this:

public void CreateTables<T>() => CreateTables(typeof(T));

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

    var fields = type.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);
 }

Or even this:

public void CreateTables(IEnumerable<Type> types) {
    if(types != null) {
        foreach(Type type in types) {
            CreateTables(type);
        }
    }
}

Upvotes: 4

Jcl
Jcl

Reputation: 28272

You can make something like this:

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

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

  var fields = type.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 then:

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

foreach(var type in types)
{
    CreateTables(type);
}

If you only use that method in the loop, you can remove the generic version, it'd not be needed at all

Upvotes: 7

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391276

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.

Upvotes: 9

Related Questions