2

我有带有实体框架的 win 表单应用程序。在我的 DbContext 中,我有两个实例:表;列。在我的 dataAccess 层中,我有以下代码

public static class DataLoader
{
    private static WdmEntities _context;

    public static List<T> GetTable<T>() where T : class
       {
           List<T> res = new List<T>();

           using (_context = new WdmEntities())
           {

               try
               {
                   res = _context.Set<T>().ToList();
               }
               catch
               {
               }
           }

           return res;
       }
}

Form.cs我有以下事件处理程序

availableTablesListBox.+= availableTablesListBox_SelectedIndexChanged;

void availableTablesListBox_SelectedIndexChanged(object sender, EventArgs e)
{
    //here i need to write code, that call GetTable<T> from DataLoader
    //according to the SelectedIndex of availableTablesListBox
}

但我可以写(不是真正的通用)

if (availableTablesListBox.SelectedIndex == 1) 
     myDataGrid.DataSource = DataLoader.GetTable<tables>();
else 
     myDataGrid.DataSource = DataLoader.GetTable<columns>();

我想写一行代码

myDataGrid.DataSource = DataTable.GetTable<WHAT WRITE HERE>();
4

2 回答 2

3

泛型被烘焙到 IL 中,因此没有单一的WHAT WRITE HERE; 您将不得不使用问题中的代码,或者使用基于传递Type实例的非通用实现。

一推,您就可以使用:

myDataGrid.DataSource = availableTablesListBox.SelectedIndex == 1
    ? (IList)DataLoader.GetTable<tables>()
    : (IList)DataLoader.GetTable<columns>();

但那是......不必要的复杂。

坦率地说,您当前的实现将完成这项工作,除了:

  • 不要吞下异常——catch忽略事情失败的事实是一个非常糟糕的主意
  • 在这里调用ToList()会强制它加载整个未过滤的表;这通常是个坏主意

如果要实现Type基于 - 的实现,可以使用非泛型Set(Type)方法而不是Set<T>方法。

于 2013-08-29T09:12:04.617 回答
1

它应该是这样的:

public static readonly MethodInfo getTableT = ((Func<List<object>>)DataLoader.GetTable<object>)
                                                   .Method
                                                   .GetGenericMethodDefinition();

(通过这些行,我们在不使用字符串的情况下获得了MethodInfo你的GetTable<T>,更易于重构)

进而

Type[] types = new[] { typeof(tables), typeof(columns) };
myDataGrid.DataSource = getTableT.MakeGenericMethod(types[availableTablesListBox.SelectedIndex])
                                 .Invoke(null, null);

显然,您必须使用反射来做到这一点,因为正如 Gravell 所说,泛型是在编译时解析的,因此如果没有反射,您就无法在运行时“构建”新的泛型。

于 2013-08-29T09:14:55.107 回答