通用类型作为变量

时间:2017-11-09 12:17:00

标签: c#

我有一个接受Generic T类的方法

  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();
   }

我有超过50种需要调用此方法的类型

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

虽然我可以这样做,但我更喜欢创建类型数组并使用for循环来调用此方法

像这样的东西

   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 

   }

有解决方法吗?还能为我节省大量代码并有效地重构内容吗?

EDIT1:

从答案中,确实像CreateTables(Type T)这样的参数可以工作,但是对于上面的第二种方法,是否还有可能?

在第二个中,提到类型为EntityData是很重要的,因为方法中的代码依赖于它。

3 个答案:

答案 0 :(得分:9)

基本上你是在尝试从反思到泛型再到反思。

由于所讨论的方法只是回到反射中,更好的方法是创建一个带类型的重载,如下所示:

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);
}

通过这种方式,您仍然可以使用特定类型(泛型)调用它,或者只需传递类型对象即可从循环中调用它。

说了这么多,如果你不能改变方法来获取Type对象,那么你需要使用反射来调用它:

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

注意!这假设您只有一种可用的方法,它是公开的等等。

答案 1 :(得分:7)

你可以做这样的事情:

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);
}

然后:

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

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

如果在循环中使用该方法,则可以删除通用版本,根本不需要它

答案 2 :(得分:4)

试试这个:

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);
 }

甚至这个:

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