基于泛型+反射的Excel万能导表工具

问题描述

  1. Excel的第一行记录字段名;
  2. 我们给这个函数输入一个泛型参数TConfig,可以让所有配置继承一个基类,拿这个基类约束一下;
  3. new Dictionary<string,TConfig>。如果导出SO,不能显示字典,就new List<TConfig>;
  4. 我们要在Excel列和TConfig字段之间建立一个关系,这个复杂度取决于你是通过字段名匹配还是顺序匹配。我们希望这个关系建立后,遍历行时可以很快的知道这一格数据要填入哪个字段。如果通过字段名匹配,读取Excel第一行每一列,查fieldDic,查到了,看字段类型,string就直接ToString,int、float、bool就tryParse。
  5. 然后要得到这个字段要转换成的类型,可以从Excel得到,也可以反射从typeof(TConfig)得到。GetFields得到TConfig的所有字段,生成一个字段名为键的字典fieldDic;
  6. 难以处理的是枚举。从fieldInfo应该是能得到具体枚举类型的。好的现在我们需要一个函数,它接受一个FieldInfo,一个字符串,如果这个FieldInfo是枚举,而且字符串是枚举的选项之一,则返回那一种枚举的那一个选项(做到的吗?)
  7. 然后还有/分隔的string、int、float、bool、枚举。在类里这会是一个List,如果用反射要先判断fieldInfo是List,再判断元素类型;
  8. 然后还有/分隔的字符串*int(比如怪物掉落多种道具、合成道具需要多种原料的数量),这种在类里会是一个字典......;
  9. 让一个函数用循环+判断处理以上所有情况......我放弃了。

把字符串尝试转换成枚举选项:

cs 复制代码
using System;
using System.Reflection;

public static class EnumFieldHelper
{
    /// <summary>
    /// 检查字段是否为枚举类型,并将字符串转换为对应的枚举值
    /// </summary>
    /// <param name="fieldType">字段的Type(FieldInfo.FieldType)</param>
    /// <param name="enumStr">要转换的枚举字符串(支持枚举名/枚举值数字)</param>
    /// <param name="enumValue">转换成功的枚举值(失败时为默认值)</param>
    /// <returns>true=转换成功,false=转换失败(非枚举/字符串不匹配)</returns>
    public static bool TryParseEnumFromFieldType(Type fieldType, string enumStr, out object enumValue)
    {
        // 初始化返回值为默认
        enumValue = null;

        // 1. 空值校验
        if (fieldType == null)
        {
            Console.WriteLine("错误:fieldType 不能为null");
            return false;
        }
        if (string.IsNullOrWhiteSpace(enumStr))
        {
            Console.WriteLine("错误:枚举字符串不能为空");
            return false;
        }

        // 2. 判断字段是否为枚举类型
        if (!fieldType.IsEnum)
        {
            Console.WriteLine($"错误:字段类型 {fieldType.Name} 不是枚举类型");
            return false;
        }

        try
        {
            // 3. 尝试将字符串转换为枚举(支持枚举名/数字字符串,忽略大小写)
            enumValue = Enum.Parse(fieldType, enumStr, ignoreCase: true);
            
            // 4. 二次校验:确保转换后的值是枚举的有效选项(防止数字超出枚举范围)
            if (Enum.IsDefined(fieldType, enumValue))
            {
                return true;
            }
            else
            {
                Console.WriteLine($"错误:字符串 {enumStr} 对应的数值不是 {fieldType.Name} 枚举的有效选项");
                enumValue = null;
                return false;
            }
        }
        catch (ArgumentException)
        {
            Console.WriteLine($"错误:无法将字符串 {enumStr} 转换为枚举 {fieldType.Name}");
            return false;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"转换枚举时发生异常:{ex.Message}");
            return false;
        }
    }

    // 简化版:直接返回枚举值(失败返回null)
    public static object ParseEnumFromFieldType(Type fieldType, string enumStr)
    {
        TryParseEnumFromFieldType(fieldType, enumStr, out object enumValue);
        return enumValue;
    }
}

生成字段字典

cs 复制代码
static Dictionary<string, FieldInfo> GetFieldDictionary<TConfig>() where TConfig : ConfigBase
    {
        var fields = typeof(TConfig).GetFields(BindingFlags.Public | BindingFlags.Instance);
        var fieldDic = new Dictionary<string, FieldInfo>();
        foreach (var field in fields)
        {
            var attr = field.GetCustomAttribute<ExcelFieldAttribute>();
            var name = attr?.Name ?? field.Name;
            fieldDic[name] = field;
        }
        return fieldDic;
    }
相关推荐
Fuxiao___1 天前
C 语言核心知识点讲义(循环 + 函数篇)
算法·c#
主宰者1 天前
C# CommunityToolkit.Mvvm全局事件
java·前端·c#
魔士于安1 天前
unity完整项目走廊
游戏·unity·游戏引擎·贴图·模型
ZoeJoy81 天前
C# + 机器视觉 + AI:从工业相机取图到 YOLO 目标检测的完整工控解决方案
人工智能·数码相机·c#
程序员正茂1 天前
在Unity3d2021.3.35中实现MQTT异步客户端
mqtt·unity·异步
海海不瞌睡(捏捏王子)1 天前
Unity YAML
unity·游戏引擎
海海不瞌睡(捏捏王子)1 天前
Unity A*寻路算法
算法·unity
weixin_423995001 天前
unity 虚拟数字人-接讯飞虚拟人
unity·游戏引擎
小贺儿开发1 天前
Unity3D 家居视频遥控效果演示
unity·udp·人机交互·网络通信·winform·远程·photon