Reputation: 3281
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
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
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
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