反射调用类方法时,如何实例化泛型List并从DataGridView填充数据
解决泛型List从DataGridView填充数据的问题
原代码存在的关键问题
- 填充完成的List实例未赋值给
parameterObject,最终传递的是新创建的空List - 错误地将
DataGridViewRow当作DataRow遍历,引发类型转换异常 - 创建List元素时实例化了
List<T>而非泛型参数T的对象 - Int64类型分支中错误创建了Int32实例
- 拼写错误:
_selecedParameters应为_selectedParameters
修正后的完整代码
private void btnTestMethod_Click(object sender, EventArgs e) { try { if (_selectedClass != null && _selectedMethod != string.Empty) { ConstructorInfo classConstructor = _selectedClass.GetConstructor(Type.EmptyTypes); object classObject = classConstructor.Invoke(new object[] { }); List<object> parameterValues = new List<object>(); List<Type> parameterTypes = new List<Type>(); for (int idx = 0; idx < pnlParameters.Controls.Count; idx++) { string parameterName = pnlParameters.Controls[idx].Name; // 修正拼写错误:_selecedParameters -> _selectedParameters var parameter = _selectedParameters.First(param => param.Name.Equals(parameterName)); if (parameter != null) { object parameterObject; parameterTypes.Add(parameter.ParameterType); switch (Type.GetTypeCode(parameter.ParameterType)) { case TypeCode.String: parameterObject = pnlParameters.Controls[idx].Text; // 简化字符串创建,无需用Activator break; case TypeCode.Int32: parameterObject = Convert.ToInt32(pnlParameters.Controls[idx].Text); break; case TypeCode.Int64: // 修正:创建Int64实例而非Int32 parameterObject = Convert.ToInt64(pnlParameters.Controls[idx].Text); break; case TypeCode.Object: parameterObject = Activator.CreateInstance(parameter.ParameterType); if (parameter.ParameterType.IsGenericType && parameter.ParameterType.GetGenericTypeDefinition() == typeof(List<>)) { Type elementType = parameter.ParameterType.GetGenericArguments()[0]; // 处理可空类型 elementType = Nullable.GetUnderlyingType(elementType) ?? elementType; // 创建泛型List实例 IList objList = (IList)Activator.CreateInstance(parameter.ParameterType); if (pnlParameters.Controls[idx] is DataGridView dgv) { // 获取T的公共可写属性列表 var properties = elementType.GetProperties() .Where(p => p.PropertyType.IsPublic && p.CanWrite) .ToList(); // 遍历DataGridView的有效行(排除新行) foreach (DataGridViewRow row in dgv.Rows) { if (row.IsNewRow) continue; // 创建T类型的实例,而非List<T> var elementObj = Activator.CreateInstance(elementType); foreach (var prop in properties) { // 匹配DataGridView列名与属性名,获取单元格值 if (dgv.Columns.Contains(prop.Name)) { object cellValue = row.Cells[prop.Name].Value; // 处理DBNull和空值,转换为目标类型 if (cellValue == DBNull.Value || cellValue == null) { prop.SetValue(elementObj, null); } else { // 转换值类型为属性类型 object convertedValue = Convert.ChangeType(cellValue, prop.PropertyType); prop.SetValue(elementObj, convertedValue); } } } objList.Add(elementObj); } // 将填充好的List赋值给parameterObject,替换空实例 parameterObject = objList; } } break; default: parameterObject = Activator.CreateInstance(parameter.ParameterType); break; } parameterValues.Add(parameterObject); } } MethodInfo classMethod = _selectedClass.GetMethod(_selectedMethod, parameterTypes.ToArray()); object testResult = classMethod.Invoke(classObject, parameterValues.ToArray()); PopulateResults(testResult); } } catch (Exception ex) { ShowErrorMessage(ex); } ResetParameters(); }
额外优化说明
- 简化了字符串、数值类型的创建逻辑,无需使用
Activator.CreateInstance,直接转换即可 - 添加了对DataGridView新行的判断,避免读取空行
- 增加了属性可写性判断,避免给只读属性赋值
- 处理了DBNull和空值的情况,确保类型转换安全
内容的提问来源于stack exchange,提问作者Kweetnix
相关产品推荐
相关产品推荐

