#nullable enable
using Furion.DatabaseAccessor;
using Furion.FriendlyException;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Xml.Linq;
namespace Admin.NET.Core
{
public static class DataConvertUtil
{
///
/// 将对象转换为Excel数据
///
///
///
///
///
///
///
///
public static void ToExcelData(List source,
IRepository sysDictTypeRep,
IRepository sysDictDataRep,
out List headers, out List> data, out string sheetName)
{
headers = new List();
data = new List>();
var type = typeof(T);
sheetName = ((DescriptionAttribute?)type.GetCustomAttribute(typeof(DescriptionAttribute), true))?.Description ?? "无";
List enumClassNames = new();
foreach (var field in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if ("Id".Equals(field.Name)) continue;
if (field.Name.EndsWith("Id")) continue;
headers.Add(((DescriptionAttribute?)field.GetCustomAttribute(typeof(DescriptionAttribute), true))?.Description ?? "无");
var dataType = StringUtil.ParseTrueType2(field.PropertyType.FullName ?? "");
if (TypeUtil.GetType(dataType)?.IsEnum ?? false)
{
if (!enumClassNames.Contains(dataType))
{
enumClassNames.Add(dataType);
}
}
}
var dictTypeList = sysDictTypeRep.DetachedEntities.Where(x => enumClassNames.Contains(x.EnumClassName)).ToList();
List dictTypeIds = dictTypeList.Select(x => x.Id).ToList();
Dictionary dictTypeDictionary = new();
dictTypeList.ForEach(x => dictTypeDictionary.Add(x.Id, x));
var dictDataList = sysDictDataRep.DetachedEntities.Where(x => dictTypeIds.Contains(x.TypeId)).ToList();
dictDataList.ForEach(x =>
{
if (dictTypeDictionary.ContainsKey(x.TypeId))
{
var dictType = dictTypeDictionary[x.TypeId];
if (dictType?.SysDictDatas == null)
{
if (dictType != null)
{
dictType.SysDictDatas = new List();
}
}
dictType?.SysDictDatas?.Add(x);
}
});
Dictionary map = new();
dictTypeList.ForEach(x =>
{
if (x?.SysDictDatas != null)
{
foreach (SysDictData dictData in x.SysDictDatas)
{
if (dictData != null) map.Add(x.EnumClassName + "#" + dictData.Code, dictData.Value);
}
}
});
foreach (var t in source)
{
List objectList = new();
foreach (var field in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var fieldName = field.Name;
if ("Id".Equals(fieldName)) continue;
if (field.Name.EndsWith("Id")) continue;
var v = t?.GetType()?.GetProperty(fieldName)?.GetValue(t);
var dataType = StringUtil.ParseTrueType2(field.PropertyType.FullName ?? "");
if (TypeUtil.GetType(dataType)?.IsEnum ?? false)
{
v = Convert.ToInt32(v);
if (map.ContainsKey(dataType + "#" + v)) v = map[dataType + "#" + v];
}
else if ("System.DateTimeOffset".Equals(dataType))
{
v = ExcelDateUtil.ToInt(
new DateTimeOffset(Convert.ToDateTime(((DateTimeOffset?)v)?.ToString("yyyy-MM-dd") ?? "1900-01-01")));
}
else if ("System.DateTime".Equals(dataType))
{
v = ExcelDateUtil.ToInt(
Convert.ToDateTime(((DateTime?)v)?.ToString("yyyy-MM-dd") ?? "1900-01-01"));
}
objectList.Add(v ?? "");
}
data.Add(objectList);
}
}
///
/// 将对象转换为Excel数据
///
///
///
///
///
///
///
///
///
public static void ToExcelData(List source,
IRepository sysDictTypeRep,
IRepository sysDictDataRep,
out List headers, out List> data, out string sheetName, out string className)
{
ToExcelData(source, sysDictTypeRep, sysDictDataRep, out headers, out data, out sheetName);
var type = typeof(T);
className = type.Name ?? "";
if (className.EndsWith("Output"))
{
className = className[..^"Output".Length];
}
}
///
/// 根据键数字生成内容字符串
///
///
///
///
///
public static string ParseStrByKeys(this T t, string[] keys)
{
var type = typeof(T);
Dictionary namePropertyInfoDict = new();
foreach (var field in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var fName = field?.Name ?? "";
if (keys.Contains(fName))
{
namePropertyInfoDict[fName] = field ?? null!;
}
}
var str = "";
foreach (var k in keys)
{
str += StringUtil.SplitChar() + namePropertyInfoDict[k]?.GetValue(t) ?? "";
}
return str;
}
///
/// 将Excel数据转换为对象列表
///
///
///
///
///
///
public static List ToObjectList(List headers, List> data, string sheetName, string[] keys, int dataStartLine, out Dictionary dict)
{
var type = typeof(T);
//去掉此验证 【Editby shaocx,2024-04-15】
//var sheetName2 = ((DescriptionAttribute?)type.GetCustomAttribute(typeof(DescriptionAttribute), true))?.Description ?? "无";
//if (!sheetName2.Equals(sheetName))
//{
// throw Oops.Oh(ErrorCode.Excel003);
//}
Dictionary indexFieldNameDict = new();
Dictionary indexFieldTypeDict = new();
Dictionary indexPropertyInfoDict = new();
Dictionary namePropertyInfoDict = new();
foreach (var field in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var desc = ((DescriptionAttribute?)field.GetCustomAttribute(typeof(DescriptionAttribute), true))?.Description ?? "无";
var fName = field.Name ?? "";
var fType = StringUtil.ParseTrueType2(field.PropertyType.FullName ?? "");
for (var i = 0; i < headers.Count; i++)
{
var header = headers[i];
if (header.Equals(desc))
{
indexFieldNameDict[i] = fName;
indexFieldTypeDict[i] = fType;
indexPropertyInfoDict[i] = field;
namePropertyInfoDict[fName] = field;
break;
}
}
}
List outputs = new();
foreach (var record in data)
{
var output = Activator.CreateInstance(type, true);
for (var i = 0; i < record.Count; i++)
{
if ("System.String".Equals(indexFieldTypeDict[i]))
{
indexPropertyInfoDict[i].SetValue(output, record[i]?.ToString() ?? "", null);
}
else if ("System.Int32".Equals(indexFieldTypeDict[i]))
{
indexPropertyInfoDict[i].SetValue(output, int.Parse(record[i]?.ToString() ?? "0"), null);
}
else if ("System.Int64".Equals(indexFieldTypeDict[i]))
{
indexPropertyInfoDict[i].SetValue(output, long.Parse(record[i]?.ToString() ?? "0"), null);
}
else if ("System.Single".Equals(indexFieldTypeDict[i]))
{
indexPropertyInfoDict[i].SetValue(output, float.Parse(record[i]?.ToString() ?? "0.0"), null);
}
else if ("System.Double".Equals(indexFieldTypeDict[i]))
{
indexPropertyInfoDict[i].SetValue(output, double.Parse(record[i]?.ToString() ?? "0.0"), null);
}
else if ("System.Decimal".Equals(indexFieldTypeDict[i]))
{
indexPropertyInfoDict[i].SetValue(output, decimal.Parse(record[i]?.ToString() ?? "0.0"), null);
}
else if ("System.Boolean".Equals(indexFieldTypeDict[i]))
{
indexPropertyInfoDict[i].SetValue(output, bool.Parse(record[i]?.ToString() ?? "False"), null);
}
else if ("System.Byte".Equals(indexFieldTypeDict[i]))
{
indexPropertyInfoDict[i].SetValue(output, byte.Parse(record[i]?.ToString() ?? "0"), null);
}
else if (TypeUtil.GetType(indexFieldTypeDict[i])?.IsEnum ?? false)
{
indexPropertyInfoDict[i].SetValue(output,
TypeUtil.GetType(indexFieldTypeDict[i])?.GetEnumByDescription(record[i]?.ToString() ?? ""), null);
}
else if ("System.DateTime".Equals(indexFieldTypeDict[i]))
{
indexPropertyInfoDict[i].SetValue(output,
ExcelDateUtil.ToDateTime(long.Parse(record[i]?.ToString() ?? "1")), null);
}
else if ("System.DateTimeOffset".Equals(indexFieldTypeDict[i]))
{
indexPropertyInfoDict[i].SetValue(output,
ExcelDateUtil.ToDateTimeOffset(long.Parse(record[i]?.ToString() ?? "1")), null);
}
}
if (output != null)
{
outputs.Add((T)output);
}
}
dict = new Dictionary();
foreach (var x in outputs)
{
var key = string.Empty;
foreach (var k in keys)
{
key += StringUtil.SplitChar() + namePropertyInfoDict[k]?.GetValue(x) ?? "";
}
if (!string.IsNullOrEmpty(key))
{
if (dict.ContainsKey(key)) throw Oops.Oh($"在{sheetName}页的第{dataStartLine}行, 唯一键冲突");
dict.Add(key, x);
}
dataStartLine += 1;
};
return outputs;
}
///
/// 获取已存在的数据
///
///
///
///
public static List> ParseUniqueKeyValueDictList(this List records, List keys, int dataStartLine, string sheetName)
{
if (keys.Count <= 0)
{
throw Oops.Oh(ErrorCode.Key001);
}
if (records.Count <= 0)
{
return new List>();
}
Type type = typeof(T);
List> uniqueKeyValueDictList = new();
var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => keys.Contains(x.Name)).ToList();
Dictionary namePropDict = new();
props.ForEach(x => namePropDict.Add(x.Name, x));
List keyStrs = new();
records.ForEach(x =>
{
Dictionary dict = new();
string keyStr = string.Empty;
keys.ForEach(y =>
{
var value = namePropDict[y]?.GetValue(x) ?? "";
if (string.IsNullOrWhiteSpace(value + "")) throw Oops.Oh($"在{sheetName}页的第{dataStartLine}行, {y}的取值不能为空");
keyStr += StringUtil.SplitChar() + value;
dict.Add(y, value);
});
if (keyStrs.Contains(keyStr)) throw Oops.Oh($"在{sheetName}页的第{dataStartLine}行, 唯一键冲突");
keyStrs.Add(keyStr);
uniqueKeyValueDictList.Add(dict);
dataStartLine++;
});
return uniqueKeyValueDictList;
}
///
/// 生成动态查询已存在记录的lamda表达式列表
///
///
///
///
///
///
public static List>> GetExpressionListByUniqueDict(List keys,
List> uniqueKeyValueDictList, int size)
{
if (keys.Count <= 0) throw Oops.Oh(ErrorCode.Key001);
var uniqueKeyValueDictListArray = uniqueKeyValueDictList.SplitList(size);
Type type = typeof(T);
var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => keys.Contains(x.Name)).ToList();
Dictionary namePropDict = new();
props.ForEach(x => namePropDict.Add(x.Name, x));
List>> filters = new();
foreach (var dictList in uniqueKeyValueDictListArray)
{
var parameter = Expression.Parameter(type, "m");
Expression? expression = null;
foreach (var item in dictList)
{
Expression? expressionItem = null;
foreach (var key in keys)
{
Expression expProperty = Expression.Property(parameter, key);
Expression> valueLamda = () => item[key];
Expression expValue = Expression.Convert(valueLamda.Body, namePropDict[key].PropertyType);
expressionItem = expressionItem == null ? Expression.Equal(expProperty, expValue) :
Expression.AndAlso(expressionItem, Expression.Equal(expProperty, expValue));
}
expression = (expression == null) ? expressionItem : Expression.OrElse(expression, expressionItem ?? null!);
}
Expression> filter = ((Expression>)Expression.Lambda(expression ?? null!, parameter));
filters.Add(filter);
}
return filters;
}
///
/// 生成动态查询已存在记录的投影lamda表达式列表
///
///
///
///
///
public static Expression> GetSelectExpressionListByUniqueDict(List keys)
{
if (keys.Count <= 0)
{
throw Oops.Oh(ErrorCode.Key001);
}
Type type = typeof(TSource);
var left = Expression.Parameter(type, "x");
var v0 = Expression.New(typeof(TResult));
List bindingList = new();
foreach (var item in keys)
{
MemberInfo speciesMember = typeof(TResult).GetMember(item)[0];
MemberExpression mem = Expression.Property(left, item);
MemberBinding memberBinding = Expression.Bind(speciesMember, mem);
bindingList.Add(memberBinding);
}
Expression body = Expression.MemberInit(v0, bindingList);
Expression> selector = (Expression>)Expression.Lambda(body, left);
return selector;
}
///
/// 获取字典生成的键字符串
///
///
///
///
///
public static string GetKey(T t, string[] keys)
{
Type type = typeof(T);
List> uniqueKeyValueDictList = new();
var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => keys.Contains(x.Name)).ToList();
Dictionary namePropDict = new();
props.ForEach(x => namePropDict.Add(x.Name, x));
string key = "";
foreach (var item in keys)
{
key += StringUtil.SplitChar() + namePropDict[item]?.GetValue(t) ?? "";
}
return key;
}
}
}