2

I am using the CreateTable method in SQLite-Net, which takes a type argument to specify what kind of table is being created. For example:

database.CreateTable<Client>();

Where client is defined as:

[Table("Client")]
public class Client
{
    [PrimaryKey]
    public int ClientID { get; set; }
    public string Name { get; set; }
    public string Type { get; set; }

}

Would create a table with the schema defined in the client class, so having ClientID, Name, and Type columns.

I would like to use a string array, holding the names of the tables I want to create, to run CreateTable on all of the classes named in the array. However I'm unsure on how to use a string as a type parameter in a generic method.

It would look something like this:

string[] tables = new string[]{"Class1","Class2"};
for(int i = 0; i < tables.Length; i++){
    database.CreateTable<tables[i]>();
}

Which would do the same thing as this:

database.CreateTable<Class1>():
database.CreateTable<Class2>();

I've already tried to do it like this:

Type tabletype = Type.GetType("Client");
database.CreateTable<tabletype>();

But I get an error which says "The type or namespace name 'tabletype' could not be found". All the tables are defined as classes in the same namespace.

Thanks.

gtsioni
  • 87
  • 1
  • 1
  • 6

3 Answers3

2

Generic type arguments have to be actual type names. They can't be expressions that evaluate to Type objects.

SQLite-Net already has a non-generic overload of CreateTable that you should use for this case:

Type tabletype = Type.GetType("Client");
database.CreateTable(tabletype);

or

string[] tables = new[] { "Class1", "Class2" };
for(int i = 0; i < tables.Length; i++) {
    Type tableType = Type.GetType(tables[i]);
    database.CreateTable(tableType);
}

In the more general case, you'd have to use reflection with MakeGenericMethod to invoke the method with a Type that comes from an expression.

Mike Zboray
  • 39,828
  • 3
  • 90
  • 122
1

You can do it with Reflection.

How do I use reflection to call a generic method?

Using your code example:

var database = GetDatabase(); // not sure what this type is.

MethodInfo method = database.GetType().GetMethod("CreateTable");
var assembly = Assembly.GetExecutingAssembly(); // Assume Class1, Class2 etc are here.

var tables = new string[] { "Class1","Class2" };

for(int i = 0; i < tables.Length; i++)
{
    MethodInfo generic = method.MakeGenericMethod(assembly.GetType(tables[i]););
    generic.Invoke(database, null);
}
Community
  • 1
  • 1
PeteGO
  • 5,597
  • 3
  • 39
  • 70
0

First off, your type name should include the namespace when calling Type.GetType and the full name of the type should be nonambiguous:

public Type GetTableType(string name) {
    const string NamespacePrefix = "MyApp.Tables.";
    return Type.GetType(NamespacePrefix + name);
}

When you have the type, you need to use reflection to call your generic method, since there is no way to determine the type at compile time:

string tableName = "BlaTable";
var genericMethodTemplate = database.GetType().GetMethod("CreateTable", new Type[0]);
//genericMethodTemplate can be seen as database.CreateTable<T>();
var tableType = GetTableType(tableName);
var genericMethod = genericMethodTemplate.MakeGenericMethod(tableType);
//now the T has been filled in with whatever table was given.
genericMethod.Invoke(database);
Bas
  • 26,772
  • 8
  • 53
  • 86