|
|
|
using Serilog;
|
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Data;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Linq.Expressions;
|
|
|
|
using System.Reflection;
|
|
|
|
using System.Security.Cryptography;
|
|
|
|
using System.Text;
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
|
|
|
namespace Wood.Util
|
|
|
|
{
|
|
|
|
|
|
|
|
public class PagedResult<T>
|
|
|
|
{
|
|
|
|
public List<T> Items { get; set; }
|
|
|
|
public int TotalItems { get; set; }
|
|
|
|
public int PageNumber { get; set; }
|
|
|
|
public int PageSize { get; set; }
|
|
|
|
public int TotalPages => (int)Math.Ceiling(TotalItems / (double)PageSize);
|
|
|
|
public bool HasPreviousPage => PageNumber > 1;
|
|
|
|
public bool HasNextPage => PageNumber < TotalPages;
|
|
|
|
|
|
|
|
public PagedResult()
|
|
|
|
{
|
|
|
|
Items = new List<T>();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static class QueryableExtensions
|
|
|
|
{
|
|
|
|
public static PagedResult<T> ToPagedResult<T>(this IQueryable<T> query, int pageNumber, int pageSize)
|
|
|
|
{
|
|
|
|
var result = new PagedResult<T>
|
|
|
|
{
|
|
|
|
PageNumber = pageNumber,
|
|
|
|
PageSize = pageSize,
|
|
|
|
TotalItems = query.Count()
|
|
|
|
};
|
|
|
|
|
|
|
|
result.Items = query
|
|
|
|
.Skip((pageNumber - 1) * pageSize)
|
|
|
|
.Take(pageSize)
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static IQueryable<T> ApplySorting<T>(this IQueryable<T> query, string sortField, string sortDirection)
|
|
|
|
{
|
|
|
|
if (string.IsNullOrEmpty(sortField))
|
|
|
|
return query;
|
|
|
|
|
|
|
|
var parameter = Expression.Parameter(typeof(T), "x");
|
|
|
|
var property = Expression.Property(parameter, sortField);
|
|
|
|
var lambda = Expression.Lambda(property, parameter);
|
|
|
|
|
|
|
|
string methodName = sortDirection?.ToLower() == "desc" ? "OrderByDescending" : "OrderBy";
|
|
|
|
var resultExpression = Expression.Call(
|
|
|
|
typeof(Queryable),
|
|
|
|
methodName,
|
|
|
|
new[] { typeof(T), property.Type },
|
|
|
|
query.Expression,
|
|
|
|
Expression.Quote(lambda));
|
|
|
|
|
|
|
|
return query.Provider.CreateQuery<T>(resultExpression);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static class DataTableHelper
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// 将泛型列表转换为DataTable
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="T">实体类型</typeparam>
|
|
|
|
/// <param name="list">泛型列表</param>
|
|
|
|
/// <param name="config">转换配置(可选)</param>
|
|
|
|
/// <returns>DataTable</returns>
|
|
|
|
public static DataTable ToDataTable<T>(this List<T> list, Action<DataTableConfig<T>> config = null)
|
|
|
|
{
|
|
|
|
if (list == null || list.Count == 0)
|
|
|
|
return new DataTable();
|
|
|
|
|
|
|
|
var tableConfig = new DataTableConfig<T>();
|
|
|
|
config?.Invoke(tableConfig);
|
|
|
|
|
|
|
|
var dataTable = new DataTable();
|
|
|
|
var properties = GetProperties(typeof(T), tableConfig);
|
|
|
|
|
|
|
|
// 创建列
|
|
|
|
foreach (var property in properties)
|
|
|
|
{
|
|
|
|
var columnType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
|
|
|
|
var columnName = tableConfig.ColumnMappings.TryGetValue(property.Name, out var mappedName)
|
|
|
|
? mappedName
|
|
|
|
: property.Name;
|
|
|
|
|
|
|
|
var column = new DataColumn(columnName, columnType);
|
|
|
|
dataTable.Columns.Add(column);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 填充数据
|
|
|
|
foreach (var item in list)
|
|
|
|
{
|
|
|
|
var row = dataTable.NewRow();
|
|
|
|
foreach (var property in properties)
|
|
|
|
{
|
|
|
|
var columnName = tableConfig.ColumnMappings.TryGetValue(property.Name, out var mappedName)
|
|
|
|
? mappedName
|
|
|
|
: property.Name;
|
|
|
|
|
|
|
|
var value = property.GetValue(item);
|
|
|
|
row[columnName] = value ?? DBNull.Value;
|
|
|
|
}
|
|
|
|
dataTable.Rows.Add(row);
|
|
|
|
}
|
|
|
|
|
|
|
|
return dataTable;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 获取需要转换的属性列表
|
|
|
|
/// </summary>
|
|
|
|
private static PropertyInfo[] GetProperties(Type type, DataTableConfig config)
|
|
|
|
{
|
|
|
|
var bindingFlags = BindingFlags.Public | BindingFlags.Instance;
|
|
|
|
if (config.IgnoreNonPublicProperties)
|
|
|
|
bindingFlags &= ~BindingFlags.NonPublic;
|
|
|
|
|
|
|
|
var properties = type.GetProperties(bindingFlags);
|
|
|
|
|
|
|
|
if (config.IgnoreProperties?.Count > 0)
|
|
|
|
{
|
|
|
|
properties = Array.FindAll(properties, p => !config.IgnoreProperties.Contains(p.Name));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config.OnlyIncludeProperties?.Count > 0)
|
|
|
|
{
|
|
|
|
properties = Array.FindAll(properties, p => config.OnlyIncludeProperties.Contains(p.Name));
|
|
|
|
}
|
|
|
|
|
|
|
|
return properties;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 数据转换配置类
|
|
|
|
/// </summary>
|
|
|
|
public class DataTableConfig<T> : DataTableConfig
|
|
|
|
{
|
|
|
|
public new Dictionary<string, string> ColumnMappings { get; } = new Dictionary<string, string>();
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 设置列映射(属性名 -> 列名)
|
|
|
|
/// </summary>
|
|
|
|
public DataTableConfig<T> MapColumn(string propertyName, string columnName)
|
|
|
|
{
|
|
|
|
ColumnMappings[propertyName] = columnName;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 设置忽略的属性
|
|
|
|
/// </summary>
|
|
|
|
public new DataTableConfig<T> IgnoreProperty(params string[] propertyNames)
|
|
|
|
{
|
|
|
|
base.IgnoreProperty(propertyNames);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 设置只包含的属性
|
|
|
|
/// </summary>
|
|
|
|
public new DataTableConfig<T> OnlyIncludeProperty(params string[] propertyNames)
|
|
|
|
{
|
|
|
|
base.OnlyIncludeProperty(propertyNames);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 设置是否忽略非公共属性(默认忽略)
|
|
|
|
/// </summary>
|
|
|
|
public new DataTableConfig<T> SetIgnoreNonPublicProperties(bool ignore = true)
|
|
|
|
{
|
|
|
|
base.SetIgnoreNonPublicProperties(ignore);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 数据转换配置基类
|
|
|
|
/// </summary>
|
|
|
|
public class DataTableConfig
|
|
|
|
{
|
|
|
|
public HashSet<string> IgnoreProperties { get; } = new HashSet<string>();
|
|
|
|
public HashSet<string> OnlyIncludeProperties { get; } = new HashSet<string>();
|
|
|
|
public Dictionary<string, string> ColumnMappings { get; } = new Dictionary<string, string>();
|
|
|
|
public bool IgnoreNonPublicProperties { get; private set; } = true;
|
|
|
|
|
|
|
|
public DataTableConfig IgnoreProperty(params string[] propertyNames)
|
|
|
|
{
|
|
|
|
foreach (var name in propertyNames)
|
|
|
|
IgnoreProperties.Add(name);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public DataTableConfig OnlyIncludeProperty(params string[] propertyNames)
|
|
|
|
{
|
|
|
|
OnlyIncludeProperties.Clear();
|
|
|
|
foreach (var name in propertyNames)
|
|
|
|
OnlyIncludeProperties.Add(name);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public DataTableConfig SetIgnoreNonPublicProperties(bool ignore = true)
|
|
|
|
{
|
|
|
|
IgnoreNonPublicProperties = ignore;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|