增加IEnumerable<>扩展方法,实现枚举类型到DataTable的转换

This commit is contained in:
falcon 2022-05-04 16:11:18 +08:00
parent 9ab32a2d4d
commit 2e1a0ad0c0
3 changed files with 191 additions and 10 deletions

View File

@ -0,0 +1,89 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Falcon.SugarApi.Test
{
/// <summary>
/// 枚举类型扩展方法
/// </summary>
[TestClass]
public class IEnumerableExtendTest
{
[TestMethod("ToDataTable测试")]
public void ToDataTableTest() {
var sw = new Stopwatch();
var list = new List<dynamic> {
new{a=1,b="b1" },
new{a=2,b="b2",c=1 },
};
sw.Start();
var r = list.ToDataTable();
sw.Stop();
Console.WriteLine($"ToDataTable转换共用时{sw.ElapsedMilliseconds}毫秒");
//测试表
Assert.IsNotNull(r);
Assert.AreEqual(3, r.Columns.Count);
Assert.AreEqual(2, r.Rows.Count);
//测试列
var col1 = r.Columns[0];
Assert.IsTrue(col1.ColumnName == "a");
Assert.IsTrue(col1.DataType == typeof(int));
var col2 = r.Columns[1];
Assert.IsTrue(col2.ColumnName == "b");
Assert.IsTrue(col2.DataType == typeof(string));
var col3 = r.Columns[2];
Assert.IsTrue(col3.ColumnName == "c");
Assert.IsTrue(col3.DataType == typeof(int));
//测试行
var row = r.Rows[0];
Assert.IsTrue(row[0].ToString() == "1");
Assert.IsTrue(row[1].ToString() == "b1");
Assert.IsTrue(row[2].ToString() == "");
row = r.Rows[1];
Assert.IsTrue((int)row[0] == 2);
Assert.IsTrue((string)row[1] == "b2");
Assert.IsTrue((int)row[2] == 1);
Console.WriteLine($"ToDataTable测试完成");
var models = new List<ToDataTableTestModel> {
new ToDataTableTestModel{ id=1, },
new ToDataTableTestModel{id=2,Name="name2" },
};
sw.Reset();
r = models.ToDataTable();
sw.Stop();
Console.WriteLine($"ToDataTable<>转换,共用时{sw.ElapsedMilliseconds}毫秒");
//测试表
Assert.IsNotNull(r);
Assert.AreEqual(2, r.Columns.Count);
Assert.AreEqual(2, r.Rows.Count);
//测试列
col1 = r.Columns[0];
Assert.IsTrue(col1.ColumnName == "id");
Assert.IsTrue(col1.DataType == typeof(int));
col2 = r.Columns[1];
Assert.IsTrue(col2.ColumnName == "Name");
Assert.IsTrue(col2.DataType == typeof(string));
//测试行
row = r.Rows[0];
Assert.IsTrue(row[0].ToString() == "1");
Assert.IsTrue(row[1].ToString() == "");
row = r.Rows[1];
Assert.IsTrue((int)row[0] == 2);
Assert.IsTrue(row[1].ToString() == "name2");
Console.WriteLine($"ToDataTable<>测试完成");
}
}
internal class ToDataTableTestModel
{
public int id { get; set; }
public string Name { get; set; }
}
}

View File

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
namespace Falcon.SugarApi
{
/// <summary>
/// 枚举扩展
/// </summary>
public static class IEnumerableExtend
{
/// <summary>
/// 枚举转换为DataTable
/// </summary>
/// <param name="source">数据枚举</param>
/// <returns>转换后Datatable</returns>
/// <exception cref="ArgumentNullException">参数为Null</exception>
public static DataTable ToDataTable(this IEnumerable<object> source) {
_ = source ?? throw new ArgumentNullException(nameof(source));
var dt = new DataTable();
if (source.Count() == 0) {
return dt;
}
for (int i = 0; i < source.Count(); i++) {
var item = source.ToArray()[i];
foreach (PropertyInfo pro in item.GetType().GetProperties()) {
if (!dt.Columns.Contains(pro.Name)) {
dt.Columns.Add(new DataColumn {
ColumnName = pro.Name,
DataType = pro.PropertyType,
});
}
}
}
foreach (var i in source) {
var row = dt.NewRow();
foreach (var p in i.GetType().GetProperties()) {
if (p.CanRead) {
var val = p.GetValue(i);
try {
row[p.Name] = val;
}
catch (Exception ex) {
throw new Exception($"值设置失败!{p.Name}:{val}", ex);
}
}
}
dt.Rows.Add(row);
}
return dt;
}
/// <summary>
/// 枚举转换为DataTable
/// </summary>
/// <typeparam name="T">枚举的元素类型</typeparam>
/// <param name="source">原数据</param>
/// <returns>转换后Datatable</returns>
/// <exception cref="ArgumentNullException">参数为Null</exception>
public static DataTable ToDataTable<T>(this IEnumerable<T> source) {
_ = source ?? throw new ArgumentNullException(nameof(source));
var type = typeof(T);
var dt = new DataTable();
var pros = typeof(T).GetProperties();
foreach (PropertyInfo p in pros) {
if (p.CanRead) {
dt.Columns.Add(new DataColumn {
ColumnName = p.Name,
DataType = p.PropertyType,
});
}
}
foreach (var i in source) {
var row = dt.NewRow();
foreach (var p in pros) {
if (p.CanRead) {
var val = p.GetValue(i);
row[p.Name] = val;
}
}
dt.Rows.Add(row);
}
return dt;
}
}
}

View File

@ -1,7 +1,7 @@
## Falcon.SugarApi
### WebApi扩展模块 [进入](/Falcon/Falcon.SugarApi/src/branch/master/Falcon.SugarApi/ApiDefinistions)
> `ApiControllerBase`webapi基类实现数据库、log、异常等基础功能。
> `ApiControllerBase`是所有webapi基类实现数据库、log、异常等基础功能。
> `ApiBaseOptionController<>`带有基本操作方法的webapi基类除了`ApiControllerBase`功能外还提供基础增删改查功能。
### Swagger扩展模块 [进入](/Falcon/Falcon.SugarApi/src/branch/master/Falcon.SugarApi/Swagger)
@ -13,6 +13,17 @@
> `SugarDbTables<T>`数据库表集合基类,可以继承该类并在其中定义`DbSet<T>`属性,这些属性会自动实例化。
> `SugarTableBase`标准表基类继承该类可提供数据表基础功能比如ID创建和修改时间等。
### 后台任务BackTask模块 [进入](/Falcon/Falcon.SugarApi/src/branch/master/Falcon.SugarApi/BackTask)
> 继承`BackgroundLongTask`可以实现一个长期位于后台执行的对象,该类通过`IServiceCollection.AddHostedService<>'进行注册。
> `RunTimespan`属性设置执行的时间间隔的秒数。
> 重写`RunAsync`方法实现一个异步任务。
> 另外可以重写`OnStart`后台任务开始,`OnStop`后台任务结束,`OnCompleted`一次执行完成和`OnException`执行中引发未处理的异常。
### 数据缓冲模块 [进入](/Falcon/Falcon.SugarApi/src/branch/master/Falcon.SugarApi/Cache)
> 通过`IServiceCollection.AddSugarRedisCache` 或 `IServiceCollection.AddSugarMemoryCache`方法注册缓冲器。
> 通过注入 `ISugarCache`同步接口 或 `ISugarCacheAsync`异步接口获取组件。
> 通过接口的`Get`和`Set`方法获取和保存缓冲值。
### XML序列化扩展模块 [进入](/Falcon/Falcon.SugarApi/src/branch/master/Falcon.SugarApi/XmlSerialize)
> `IServiceCollection.AddXmlSerializeFactory`方法注册xml序列化工厂`XmlSerializeFactory`可以通过该工厂实例化一个XML序列化器。
@ -26,13 +37,6 @@
### Object扩展方法
> `CloneTo`和`CloneFrom`实现将对象属性赋值到目标对象同名属性中,此为浅表复制。
### 后台任务BackTask模块 [进入](/Falcon/Falcon.SugarApi/src/branch/master/Falcon.SugarApi/BackTask)
> 继承`BackgroundLongTask`可以实现一个长期位于后台执行的对象,该类通过`IServiceCollection.AddHostedService<>'进行注册。
> `RunTimespan`属性设置执行的时间间隔的秒数。
> 重写`RunAsync`方法实现一个异步任务。
> 另外可以重写`OnStart`后台任务开始,`OnStop`后台任务结束,`OnCompleted`一次执行完成和`OnException`执行中引发未处理的异常。
### IEnumerable扩展方法
> `ToDataTable`和`ToDataTable<>`分别实现将枚举类型转换为DataTable的方法区别是一个针对Object枚举一个针对具体类型枚举尽量使用泛型版本更加高效。
### 数据缓冲模块 [进入](/Falcon/Falcon.SugarApi/src/branch/master/Falcon.SugarApi/Cache)
> 通过`IServiceCollection.AddSugarRedisCache` 或 `IServiceCollection.AddSugarMemoryCache`方法注册缓冲器。
> 通过注入 `ISugarCache`同步接口 或 `ISugarCacheAsync`异步接口获取组件。
> 通过接口的`Get`和`Set`方法获取和保存缓冲值。