You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

反射调用类方法时,如何实例化泛型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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 05:02:06