开源 - Ideal库 - Excel帮助类,TableHelper实现(二)

news/2024/11/30 0:22:43/文章来源:https://www.cnblogs.com/hugogoos/p/18577563

书接上回,我们今天开始实现对象集合与DataTable的相互转换。

01、接口设计

上文中已经详细讲解了整体设计思路以及大致设计了需要哪些方法。下面我们先针对上文设计思想确定对外提供的接口。具体接口如下:

//根据列名数组创建表格
public static DataTable Create(string[] columnNames, string? tableName = null);//根据列名-类型键值对创建表格
public static DataTable Create(Dictionary<string, Type> columns, string? tableName = null);//根据类创建表格
//如果设置DescriptionAttribute,则将特性值作为表格的列名称
//否则将属性名作为表格的列名称
public static DataTable Create<T>(string? tableName = null);//把表格转换为实体对象集合
//如果设置DescriptionAttribute,则将特性值作为表格的列名称
//否则将属性名作为表格的列名称
public static IEnumerable<T> ToModels<T>(DataTable dataTable);//把实体对象集合转为表格
//如果设置DescriptionAttribute,则将特性值作为表格的列名称
//否则将属性名作为表格的列名称
public static DataTable ToDataTable<T>(IEnumerable<T> models, string? tableName = null);//把一维数组作为一列转换为表格
public static DataTable ToDataTableWithColumnArray<TColumn>(TColumn[] array, string? tableName = null, string? columnName = null);//把一维数组作为一行转换为表格
public static DataTable ToDataTableWithRowArray<TRow>(TRow[] array, string? tableName = null);//行列转置
public static DataTable Transpose(DataTable dataTable, bool isColumnNameAsData = true);

02、根据列名数组创建表格

该方法实现比较简单,我们直接看代码:

//根据列名数组创建表格
public static DataTable Create(string[] columnNames, string? tableName = null)
{var table = new DataTable(tableName);foreach (var columnName in columnNames){table.Columns.Add(columnName);}return table;
}

我们进行一个简单的单元测试:

[Fact]
public void Create()
{//正常创建成功var columnNames = new string[] { "A", "B" };var table = TableHelper.Create(columnNames);Assert.Equal("", table.TableName);Assert.Equal(2, table.Columns.Count);Assert.Equal(columnNames[0], table.Columns[0].ColumnName);Assert.Equal(columnNames[1], table.Columns[1].ColumnName);Assert.Equal(typeof(string), table.Columns[0].DataType);Assert.Equal(typeof(string), table.Columns[1].DataType);//验证表名table = TableHelper.Create(columnNames, "test");Assert.Equal("test", table.TableName);//验证列名不能重复columnNames = new string[] { "A", "A" };Assert.Throws<DuplicateNameException>(() => TableHelper.Create(columnNames));
}

03、根据列名-类型键值对创建表格

此方法是上一个方法的补充,默认直接根据列名创建表格,则所有列的数据类型都是string类型,而此方法可以指定每列的数据类型,实现也很简单,代码如下:

//根据列名-类型键值对创建表格
public static DataTable Create(Dictionary<string, Type> columns, string? tableName = null)
{var table = new DataTable(tableName);foreach (var column in columns){table.Columns.Add(column.Key, column.Value);}return table;
}

04、根据类创建表格

该方法是将类的属性名作为表格的列名称,属性对应的类型作为表格列的数据类型,把类转为表格。

同时我们需要约束类只能为结构体或类,而不能是枚举、基础类型、以及集合类型、委托、接口等。显然我们很难通过泛型约束达到我们的需求,因此我们首先需要对该方法的泛型进行类型校验。

校验成功后,我们只需要通过反射即可拿到类的所有属性信息,即可创建表格。同时我们约定如果属性设置了DescriptionAttribute特性,则特性值作为列名,如果没有设置特性则取属性名称作为列名。

//根据类创建表格
//如果设置DescriptionAttribute,则将特性值作为表格的列名称
//否则将属性名作为表格的列名称
public static DataTable Create<T>(string? tableName = null)
{//T必须是结构体或类,并且不能是集合类型AssertTypeValid<T>();//获取类的所有公共属性var properties = typeof(T).GetProperties();var columns = new Dictionary<string, Type>();foreach (var property in properties){//根据属性获取列名var columnName = GetColumnName(property);//组织列名-类型键值对columns.Add(columnName, property.PropertyType);}return Create(columns, tableName);
}//断言类型有效性
private static void AssertTypeValid<T>()
{var type = typeof(T);if (type.IsValueType && !type.IsEnum && !type.IsPrimitive){//是值类型,但是不是枚举或基础类型return;}else if (typeof(T).IsClass && !typeof(IEnumerable).IsAssignableFrom(typeof(T))){//是类类型,但是不是集合类型,同时也不是委托、接口类型return;}throw new InvalidOperationException("T must be a struct or class and cannot be a collection type.");
}//根据属性获取列名称
private static string GetColumnName(PropertyInfo property)
{//获取描述特性var attribute = property.GetCustomAttribute<DescriptionAttribute>();//如果存在描述特性则返回描述,否则返回属性名称return attribute?.Description ?? property.Name;
}

下面我们针对枚举、字符串,基础类型、集合等情况进行详细的单元测试,代码如下:

[Fact]
public void Create_T()
{//验证枚举var expectedMessage = "T must be a struct or class and cannot be a collection type.";var exception1 = Assert.Throws<InvalidOperationException>(() => TableHelper.Create<StatusEnum>());Assert.Equal(expectedMessage, exception1.Message);//验证基础类型var exception2 = Assert.Throws<InvalidOperationException>(() => TableHelper.Create<int>());Assert.Equal(expectedMessage, exception2.Message);//验证字符串类型var exception3 = Assert.Throws<InvalidOperationException>(() => TableHelper.Create<string>());Assert.Equal(expectedMessage, exception3.Message);//验证集合var exception4 = Assert.Throws<InvalidOperationException>(() => TableHelper.Create<Dictionary<string, Type>>());Assert.Equal(expectedMessage, exception4.Message);//验证正常情况var table = TableHelper.Create<Student<double>>();Assert.Equal("", table.TableName);Assert.Equal(3, table.Columns.Count);Assert.Equal("标识", table.Columns[0].ColumnName);Assert.Equal("姓名", table.Columns[1].ColumnName);Assert.Equal("Age", table.Columns[2].ColumnName);Assert.Equal(typeof(string), table.Columns[0].DataType);Assert.Equal(typeof(string), table.Columns[1].DataType);Assert.Equal(typeof(double), table.Columns[2].DataType);
}

:测试方法代码以及示例源码都已经上传至代码库,有兴趣的可以看看。https://gitee.com/hugogoos/Ideal

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/843742.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大语言模型中的MoE

1.概述 MoE代表“混合专家模型”(Mixture of Experts),这是一种架构设计,通过将不同的子模型(即专家)结合起来进行任务处理。与传统的模型相比,MoE结构能够动态地选择并激活其中一部分专家,从而显著提升模型的效率和性能。尤其在计算和参数规模上,MoE架构能够在保持较…

ssh控制远程设备连接wifi

查看wifisudo nmcli device wifi连接wifisudo nmcli device wifi connect MERCURY_21B8 password 密码提示连接成功Device wlan0 successfully activated with 5c7d67b4-145d-4848-83cf-3b51795503fb

Kubeapps可视化管理Helm Chart包

目录一.基于helm部署kubeapps1.kubeapps介绍2.添加kubeapps的repo3.搜索kubeapps4.下载指定的kubeapps版本5.基于helm部署kubeapps6.访问kubeapps的WebUI二.通过kubeapps部署应用案例1 通过kubeapps查看已经部署的Chart2.通过kubeapps搜索Chart信息 一.基于helm部署kubeapps 1.…

剪映设置封面时候如何防止文字遮挡人物 All In One

剪映设置封面时候如何防止文字遮挡人物 All In One PS 图层叠加 / 前景后景 / 透明度 照片 人物抠图 + 画中画剪映设置封面时候如何防止文字遮挡人物 All In One 原理分析 PS 图层叠加 / 前景后景 / 透明度 照片 人物抠图 + 画中画 solutionsFilmora ???人物抠图 图层叠加 图…

聊一下怎么10分钟速水中危CVE

怎么在10分钟里速水一个中危CVE题目是真的。今天晚上刚接触关于CVE的审计和提交。只能说:牛逼的是真牛逼,水的是真水。 我接下来教你,怎么在10分钟里找到一个CVE的中危漏洞并且提交。然后你就可以去咸鱼接单了,一个一铂快 打开https://code-projects.org/ 随机找一个水项目…

2024-2025-1 20241403 《计算机基础与程序设计》第十周学习总结

学期2024-2025-1 学号20241403 《计算机基础与程序设计》第十周学习总结 作业信息这个作业属于哪个课程 <班级的链接>2024-2025-1-计算机基础与程序设计](https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP)这个作业要求在哪里 <作业要求的链接>2024-2025-1计…

《Django 5 By Example》阅读笔记:p388-p454

《Django 5 By Example》学习第 15 天,p388-p454 总结,总计 66 页。 一、技术总结 1.celery 我觉得书中这种用法太简单了。 2.flower 用于监控 celery。 # 安装 pip install flower # 启动 celery -A myshop flower --basic-auth=root:root # 访问 http://127.0.0.1:555…

java学习11.29

去年22级报销管理系统基本完成,出差报销申请撤销,审批功能基本完成

Kustomize 设计理念与使用说明

Kustomize 设计理念与使用说明 一、设计理念 Kustomize 的设计理念是基于"基础配置 + 补丁"的模式,这里解释一下为什么需要在 base 目录下创建基础配置:基础配置的重要性:base 目录下的配置是所有环境共享的基础配置 包含了服务最基本的定义和配置 确保了不同环境…

【评价指标】ROC曲线与AUC

一、前置知识 ​ 真阳性(TPR):正样本被正确分类个数与所有正样本的总数的比值 \[TPR = \frac{TP}{TP+FN} \]​ 假阳性(FPR):负样本被错误分类个数与所有负样本的总数的比值 \[FPR=\frac{FN}{FN+TN} \]​ 其中,TP表示正确分类的正样本,TN表示正确分类的负样本,FN表示错误分…

overleaf中使用中文

用的是这个博客里面的方法三,很方便。 https://blog.csdn.net/m0_52037292/article/details/109768317\usepackage{CJKutf8} \usepackage{CJKutf8}\begin{document}\begin{CJK*}{UTF8}{gbsn} 数学、中英文皆可以混排。You can intersperse math, Chinese and English (Latin …

20222409 2024-2025-1 《网络与系统攻防技术》实验五实验报告

1.实验内容 1.1 本周学习内容 本周学习了信息收集与渗透测试相关技术,主要包括Metasploit、nmap和Nessus的使用。Metasploit是渗透测试框架,能提供多种攻击模块,如远程代码执行、提权和后渗透功能(如键盘记录、文件操作等),可用于模拟攻击和漏洞利用; nmap被用于扫描目标…