C# 在不知道特定类型的情况下访问泛型方法
C# Accessing generic Method without knowing specific type
我有一个方法可以使用反射将 List<T>
转换为 DataTable
。我想通过传递多个列表来利用该方法创建数据集,其中每个列表可能包含不同类型的对象。
下面是给我编译时错误的代码:
"The type arguments for method 'ExportToExcel.CreateExcelFile.ListToDataTable<T>(System.Collections.Generic.List<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly
."
- 在行“var dt = Util.ListToDataTable(item);
”
public static class Util
{
public static DataSet GetDataSet(List<string> title, List<IList> data)
{
DataSet ds = new DataSet();
int idx= 0;
foreach (var item in data)
{
//here I get compile time error "The type arguments for method
// 'ExportToExcel.CreateExcelFile.ListToDataTable<T>
// (System.Collections.Generic.List<T>)' cannot be inferred from the usage.
// Try specifying the type arguments explicitly. "
var dt = Util.ListToDataTable(item);
if (title.Count >= idx)
{
dt.TableName = title[idx];
}
idx++;
ds.Tables.Add(dt);
}
return ds;
}
public static System.Data.DataTable ListToDataTable<T>(List<T> list)
{
var dt = new System.Data.DataTable();
foreach (PropertyInfo info in typeof(T).GetProperties())
{
dt.Columns.Add(new DataColumn(info.Name, info.PropertyType));
}
foreach (T t in list)
{
DataRow row = dt.NewRow();
foreach (PropertyInfo info in typeof(T).GetProperties())
{
row[info.Name] = info.GetValue(t, null);
}
dt.Rows.Add(row);
}
return dt;
}
}
这是我调用的测试方法
[TestMethod]
public void TestDataSetGeneration_WithMultipleLists()
{
IList list = new List<User>();
list.Add(new User(){FirstName = "Mahesh", LastName = "Chaudhari", IsExternal = true, UpdatedOn = DateTime.Now});
list.Add(new User(){FirstName = "Mahesh1",LastName = "Chaudhari1",IsExternal = true,UpdatedOn = DateTime.Now});
list.Add(new User(){FirstName = "Mahesh2",LastName = "Chaudhari2",IsExternal = false,UpdatedOn = DateTime.Now});
IList hcps = new List<HCPUser>() { new HCPUser(){FirstName = "HCP1",LastName = "HCP1"}};
var lists = new List<IList>();
lists.Add(list);
lists.Add(hcps);
var titles = new List<String> { "Users", "HCPs"};
var result = Util.GetDataSet(titles ,lists );
Assert.IsTrue(result != null);
}
我认为方法 Util.ListToDataTable 需要仅在运行时获取的特定类型。在这种情况下,我将如何调用此方法?
您可以使用 MethodInfo.MakeGenericMethod 构造通用 MethodInfo
对象并通过反射调用它,但我认为 ListToDataTable
方法没有理由需要通用。
一种选择是将 List<T>
更改为非通用的内容,例如 IEnumerable
。不过,您必须通过从列表中获取第一个元素来找出类型。
另一种选择是 LINQ:
public static System.Data.DataTable ListToDataTable<T>( object[] list )
{
....
}
var dt = ListToDataTable( item.Cast<object>().ToArray() );
如果列表为空,这两个选项都将无法找到类型。也许其他人有更好的方法。
编辑:我现在看到你的数据从一开始就是非泛型的IList
,所以类型基本上已经丢失了。
似乎代码比需要的稍微复杂一些。您以不等于泛型类型的泛型类型结束。如前一个答案中所问,简单地使用 IEnumerable
有什么问题?下面的代码通过了您的单元测试。
public static DataSet GetDataSet(List<string> title, IEnumerable<IEnumerable> data)
{
DataSet ds = new DataSet();
int idx = 0;
foreach (var item in data)
{
//here I get compile time error "The type arguments for method
// 'ExportToExcel.CreateExcelFile.ListToDataTable<T>
// (System.Collections.Generic.List<T>)' cannot be inferred from the usage.
// Try specifying the type arguments explicitly. "
var dt = Util.ListToDataTable(item);
if (title.Count >= idx)
{
dt.TableName = title[idx];
}
idx++;
ds.Tables.Add(dt);
}
return ds;
}
public static System.Data.DataTable ListToDataTable(IEnumerable list)
{
var dt = new System.Data.DataTable();
var itm = list.OfType<object>().FirstOrDefault();
if (itm == null)
return dt;
var typeProperties = itm.GetType().GetProperties();
foreach (PropertyInfo info in typeProperties)
{
dt.Columns.Add(new DataColumn(info.Name, info.PropertyType));
}
foreach (var t in list)
{
DataRow row = dt.NewRow();
foreach (PropertyInfo info in typeProperties)
{
row[info.Name] = info.GetValue(t, null);
}
dt.Rows.Add(row);
}
return dt;
}
我有一个方法可以使用反射将 List<T>
转换为 DataTable
。我想通过传递多个列表来利用该方法创建数据集,其中每个列表可能包含不同类型的对象。
下面是给我编译时错误的代码:
"The type arguments for method 'ExportToExcel.CreateExcelFile.ListToDataTable<T>(System.Collections.Generic.List<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly
."
- 在行“var dt = Util.ListToDataTable(item);
”
public static class Util
{
public static DataSet GetDataSet(List<string> title, List<IList> data)
{
DataSet ds = new DataSet();
int idx= 0;
foreach (var item in data)
{
//here I get compile time error "The type arguments for method
// 'ExportToExcel.CreateExcelFile.ListToDataTable<T>
// (System.Collections.Generic.List<T>)' cannot be inferred from the usage.
// Try specifying the type arguments explicitly. "
var dt = Util.ListToDataTable(item);
if (title.Count >= idx)
{
dt.TableName = title[idx];
}
idx++;
ds.Tables.Add(dt);
}
return ds;
}
public static System.Data.DataTable ListToDataTable<T>(List<T> list)
{
var dt = new System.Data.DataTable();
foreach (PropertyInfo info in typeof(T).GetProperties())
{
dt.Columns.Add(new DataColumn(info.Name, info.PropertyType));
}
foreach (T t in list)
{
DataRow row = dt.NewRow();
foreach (PropertyInfo info in typeof(T).GetProperties())
{
row[info.Name] = info.GetValue(t, null);
}
dt.Rows.Add(row);
}
return dt;
}
}
这是我调用的测试方法
[TestMethod]
public void TestDataSetGeneration_WithMultipleLists()
{
IList list = new List<User>();
list.Add(new User(){FirstName = "Mahesh", LastName = "Chaudhari", IsExternal = true, UpdatedOn = DateTime.Now});
list.Add(new User(){FirstName = "Mahesh1",LastName = "Chaudhari1",IsExternal = true,UpdatedOn = DateTime.Now});
list.Add(new User(){FirstName = "Mahesh2",LastName = "Chaudhari2",IsExternal = false,UpdatedOn = DateTime.Now});
IList hcps = new List<HCPUser>() { new HCPUser(){FirstName = "HCP1",LastName = "HCP1"}};
var lists = new List<IList>();
lists.Add(list);
lists.Add(hcps);
var titles = new List<String> { "Users", "HCPs"};
var result = Util.GetDataSet(titles ,lists );
Assert.IsTrue(result != null);
}
我认为方法 Util.ListToDataTable 需要仅在运行时获取的特定类型。在这种情况下,我将如何调用此方法?
您可以使用 MethodInfo.MakeGenericMethod 构造通用 MethodInfo
对象并通过反射调用它,但我认为 ListToDataTable
方法没有理由需要通用。
一种选择是将 List<T>
更改为非通用的内容,例如 IEnumerable
。不过,您必须通过从列表中获取第一个元素来找出类型。
另一种选择是 LINQ:
public static System.Data.DataTable ListToDataTable<T>( object[] list )
{
....
}
var dt = ListToDataTable( item.Cast<object>().ToArray() );
如果列表为空,这两个选项都将无法找到类型。也许其他人有更好的方法。
编辑:我现在看到你的数据从一开始就是非泛型的IList
,所以类型基本上已经丢失了。
似乎代码比需要的稍微复杂一些。您以不等于泛型类型的泛型类型结束。如前一个答案中所问,简单地使用 IEnumerable
有什么问题?下面的代码通过了您的单元测试。
public static DataSet GetDataSet(List<string> title, IEnumerable<IEnumerable> data)
{
DataSet ds = new DataSet();
int idx = 0;
foreach (var item in data)
{
//here I get compile time error "The type arguments for method
// 'ExportToExcel.CreateExcelFile.ListToDataTable<T>
// (System.Collections.Generic.List<T>)' cannot be inferred from the usage.
// Try specifying the type arguments explicitly. "
var dt = Util.ListToDataTable(item);
if (title.Count >= idx)
{
dt.TableName = title[idx];
}
idx++;
ds.Tables.Add(dt);
}
return ds;
}
public static System.Data.DataTable ListToDataTable(IEnumerable list)
{
var dt = new System.Data.DataTable();
var itm = list.OfType<object>().FirstOrDefault();
if (itm == null)
return dt;
var typeProperties = itm.GetType().GetProperties();
foreach (PropertyInfo info in typeProperties)
{
dt.Columns.Add(new DataColumn(info.Name, info.PropertyType));
}
foreach (var t in list)
{
DataRow row = dt.NewRow();
foreach (PropertyInfo info in typeProperties)
{
row[info.Name] = info.GetValue(t, null);
}
dt.Rows.Add(row);
}
return dt;
}