添加项目文件。
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
public static class CloneExtension
|
||||
{
|
||||
|
||||
public static T Clone<T>(this T source)
|
||||
{
|
||||
// Don't serialize a null object, simply return the default for that object
|
||||
if (Object.ReferenceEquals(source, null))
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
|
||||
var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };
|
||||
var serializeSettings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
|
||||
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source, serializeSettings), deserializeSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
public static class ConvertJsonExtension
|
||||
{
|
||||
#region 私有方法
|
||||
/// <summary>
|
||||
/// 过滤特殊字符
|
||||
/// </summary>
|
||||
/// <param name="s">字符串</param>
|
||||
/// <returns>json字符串</returns>
|
||||
private static string String2Json(String s)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
{
|
||||
char c = s.ToCharArray()[i];
|
||||
switch (c)
|
||||
{
|
||||
case '\"':
|
||||
sb.Append("\\\""); break;
|
||||
case '\\':
|
||||
sb.Append("\\\\"); break;
|
||||
case '/':
|
||||
sb.Append("\\/"); break;
|
||||
case '\b':
|
||||
sb.Append("\\b"); break;
|
||||
case '\f':
|
||||
sb.Append("\\f"); break;
|
||||
case '\n':
|
||||
sb.Append("\\n"); break;
|
||||
case '\r':
|
||||
sb.Append("\\r"); break;
|
||||
case '\t':
|
||||
sb.Append("\\t"); break;
|
||||
default:
|
||||
sb.Append(c); break;
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// 格式化字符型、日期型、布尔型
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
private static string StringFormat(string str, Type type)
|
||||
{
|
||||
if (type == typeof(string))
|
||||
{
|
||||
str = String2Json(str);
|
||||
str = "\"" + str + "\"";
|
||||
}
|
||||
else if (type == typeof(DateTime))
|
||||
{
|
||||
str = "\"" + str + "\"";
|
||||
}
|
||||
else if (type == typeof(bool))
|
||||
{
|
||||
str = str.ToLower();
|
||||
}
|
||||
else if (type != typeof(string) && string.IsNullOrEmpty(str))
|
||||
{
|
||||
str = "\"" + str + "\"";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region list转换成JSON
|
||||
/// <summary>
|
||||
/// list转换为Json
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
public static string ListToJson<T>(this IList<T> list)
|
||||
{
|
||||
object obj = list[0];
|
||||
return ListToJson<T>(list, obj.GetType().Name);
|
||||
}
|
||||
/// <summary>
|
||||
/// list转换为json
|
||||
/// </summary>
|
||||
/// <typeparam name="T1"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="p"></param>
|
||||
/// <returns></returns>
|
||||
private static string ListToJson<T>(this IList<T> list, string JsonName)
|
||||
{
|
||||
if (list.Count == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
StringBuilder Json = new StringBuilder();
|
||||
if (string.IsNullOrEmpty(JsonName))
|
||||
JsonName = list[0].GetType().Name;
|
||||
Json.Append("{\"" + JsonName + "\":[");
|
||||
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
T obj = Activator.CreateInstance<T>();
|
||||
PropertyInfo[] pi = obj.GetType().GetProperties();
|
||||
Json.Append("{");
|
||||
for (int j = 0; j < pi.Length; j++)
|
||||
{
|
||||
Type type = pi[j].GetValue(list[i], null).GetType();
|
||||
Json.Append("\"" + pi[j].Name.ToString() + "\":" + StringFormat(pi[j].GetValue(list[i], null).ToString(), type));
|
||||
if (j < pi.Length - 1)
|
||||
{
|
||||
Json.Append(",");
|
||||
}
|
||||
}
|
||||
Json.Append("}");
|
||||
if (i < list.Count - 1)
|
||||
{
|
||||
Json.Append(",");
|
||||
}
|
||||
}
|
||||
Json.Append("]}");
|
||||
return Json.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 对象转换为Json
|
||||
/// <summary>
|
||||
/// 对象转换为json
|
||||
/// </summary>
|
||||
/// <param name="jsonObject">json对象</param>
|
||||
/// <returns>json字符串</returns>
|
||||
public static string ToJson(this object jsonObject)
|
||||
{
|
||||
string jsonString = "{";
|
||||
PropertyInfo[] propertyInfo = jsonObject.GetType().GetProperties();
|
||||
for (int i = 0; i < propertyInfo.Length; i++)
|
||||
{
|
||||
object objectValue = propertyInfo[i].GetGetMethod().Invoke(jsonObject, null);
|
||||
string value = string.Empty;
|
||||
if (objectValue is DateTime || objectValue is Guid || objectValue is TimeSpan)
|
||||
{
|
||||
value = "'" + objectValue.ToString() + "'";
|
||||
}
|
||||
else if (objectValue is string)
|
||||
{
|
||||
value = "'" + ToJson(objectValue.ToString()) + "'";
|
||||
}
|
||||
else if (objectValue is IEnumerable)
|
||||
{
|
||||
value = ToJson((IEnumerable)objectValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = ToJson(objectValue.ToString());
|
||||
}
|
||||
jsonString += "\"" + ToJson(propertyInfo[i].Name) + "\":" + value + ",";
|
||||
}
|
||||
jsonString.Remove(jsonString.Length - 1, jsonString.Length);
|
||||
return jsonString + "}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 对象集合转换为json
|
||||
/// <summary>
|
||||
/// 对象集合转换为json
|
||||
/// </summary>
|
||||
/// <param name="array">对象集合</param>
|
||||
/// <returns>json字符串</returns>
|
||||
public static string ToJson(this IEnumerable array)
|
||||
{
|
||||
string jsonString = "{";
|
||||
foreach (object item in array)
|
||||
{
|
||||
jsonString += ToJson(item) + ",";
|
||||
}
|
||||
jsonString.Remove(jsonString.Length - 1, jsonString.Length);
|
||||
return jsonString + "]";
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 普通集合转换Json
|
||||
/// <summary>
|
||||
/// 普通集合转换Json
|
||||
/// </summary>
|
||||
/// <param name="array">集合对象</param>
|
||||
/// <returns>Json字符串</returns>
|
||||
public static string ToArrayString(this IEnumerable array)
|
||||
{
|
||||
string jsonString = "[";
|
||||
foreach (object item in array)
|
||||
{
|
||||
jsonString = ToJson(item.ToString()) + ",";
|
||||
}
|
||||
jsonString.Remove(jsonString.Length - 1, jsonString.Length);
|
||||
return jsonString + "]";
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DataSet转换为Json
|
||||
/// <summary>
|
||||
/// DataSet转换为Json
|
||||
/// </summary>
|
||||
/// <param name="dataSet">DataSet对象</param>
|
||||
/// <returns>Json字符串</returns>
|
||||
public static string ToJson(this DataSet dataSet)
|
||||
{
|
||||
string jsonString = "{";
|
||||
foreach (DataTable table in dataSet.Tables)
|
||||
{
|
||||
jsonString += "\"" + table.TableName + "\":" + ToJson(table) + ",";
|
||||
}
|
||||
jsonString = jsonString.TrimEnd(',');
|
||||
return jsonString + "}";
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Datatable转换为Json
|
||||
/// <summary>
|
||||
/// Datatable转换为Json
|
||||
/// </summary>
|
||||
/// <param name="table">Datatable对象</param>
|
||||
/// <returns>Json字符串</returns>
|
||||
public static string ToJson(this DataTable dt)
|
||||
{
|
||||
StringBuilder jsonString = new StringBuilder();
|
||||
jsonString.Append("[");
|
||||
DataRowCollection drc = dt.Rows;
|
||||
for (int i = 0; i < drc.Count; i++)
|
||||
{
|
||||
jsonString.Append("{");
|
||||
for (int j = 0; j < dt.Columns.Count; j++)
|
||||
{
|
||||
string strKey = dt.Columns[j].ColumnName;
|
||||
string strValue = drc[i][j].ToString();
|
||||
Type type = dt.Columns[j].DataType;
|
||||
jsonString.Append("\"" + strKey + "\":");
|
||||
strValue = StringFormat(strValue, type);
|
||||
if (j < dt.Columns.Count - 1)
|
||||
{
|
||||
jsonString.Append(strValue + ",");
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonString.Append(strValue);
|
||||
}
|
||||
}
|
||||
jsonString.Append("},");
|
||||
}
|
||||
jsonString.Remove(jsonString.Length - 1, 1);
|
||||
jsonString.Append("]");
|
||||
return jsonString.ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// DataTable转换为Json
|
||||
/// </summary>
|
||||
public static string ToJson(this DataTable dt, string jsonName)
|
||||
{
|
||||
StringBuilder Json = new StringBuilder();
|
||||
if (string.IsNullOrEmpty(jsonName))
|
||||
jsonName = dt.TableName;
|
||||
Json.Append("{\"" + jsonName + "\":[");
|
||||
if (dt.Rows.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < dt.Rows.Count; i++)
|
||||
{
|
||||
Json.Append("{");
|
||||
for (int j = 0; j < dt.Columns.Count; j++)
|
||||
{
|
||||
Type type = dt.Rows[i][j].GetType();
|
||||
Json.Append("\"" + dt.Columns[j].ColumnName.ToString() + "\":" + StringFormat(dt.Rows[i][j].ToString(), type));
|
||||
if (j < dt.Columns.Count - 1)
|
||||
{
|
||||
Json.Append(",");
|
||||
}
|
||||
}
|
||||
Json.Append("}");
|
||||
if (i < dt.Rows.Count - 1)
|
||||
{
|
||||
Json.Append(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
Json.Append("]}");
|
||||
return Json.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DataReader转换为Json
|
||||
/// <summary>
|
||||
/// DataReader转换为Json
|
||||
/// </summary>
|
||||
/// <param name="dataReader">DataReader对象</param>
|
||||
/// <returns>Json字符串</returns>
|
||||
public static string ReaderJson(this IDataReader dataReader)
|
||||
{
|
||||
StringBuilder jsonString = new StringBuilder();
|
||||
Dictionary<string, Type> ModelField = new Dictionary<string, Type>();
|
||||
for (int i = 0; i < dataReader.FieldCount; i++)
|
||||
{
|
||||
ModelField.Add(dataReader.GetName(i), dataReader.GetFieldType(i));
|
||||
}
|
||||
jsonString.Append("[");
|
||||
while (dataReader.Read())
|
||||
{
|
||||
jsonString.Append("{");
|
||||
foreach (KeyValuePair<string, Type> keyVal in ModelField)
|
||||
{
|
||||
Type type = keyVal.Value;
|
||||
string strKey = keyVal.Key;
|
||||
string strValue = dataReader[strKey].ToString();
|
||||
jsonString.Append("\"" + strKey + "\":");
|
||||
strValue = StringFormat(strValue, type);
|
||||
jsonString.Append(strValue + ",");
|
||||
}
|
||||
jsonString.Remove(jsonString.Length - 1, 1);
|
||||
jsonString.Append("},");
|
||||
}
|
||||
dataReader.Close();
|
||||
jsonString.Remove(jsonString.Length - 1, 1);
|
||||
jsonString.Append("]");
|
||||
return jsonString.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
public static T DeserializeObject<T>(this string entityString)
|
||||
{
|
||||
if (string.IsNullOrEmpty(entityString))
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
if (entityString == "{}")
|
||||
{
|
||||
entityString = "[]";
|
||||
}
|
||||
return JsonConvert.DeserializeObject<T>(entityString);
|
||||
}
|
||||
|
||||
public static string Serialize(this object obj, JsonSerializerSettings formatDate = null)
|
||||
{
|
||||
if (obj == null) return null;
|
||||
formatDate = formatDate ?? new JsonSerializerSettings
|
||||
{
|
||||
DateFormatString = "yyyy-MM-dd HH:mm:ss"
|
||||
};
|
||||
return JsonConvert.SerializeObject(obj, formatDate);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
public static class EnumToSelectExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 将枚举转换成字典(枚举,自定义描述)
|
||||
/// </summary>
|
||||
/// <typeparam name="TEnum"></typeparam>
|
||||
/// <param name="exceptList">需要排除的枚举</param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<object, string> ToSelect<TEnum>( params TEnum[] exceptList) where TEnum : struct, Enum
|
||||
{
|
||||
var type = typeof(TEnum);
|
||||
var dict = new Dictionary<object, string>();
|
||||
foreach (var value in Enum.GetValues<TEnum>())
|
||||
//foreach (var value in type.GetEnumValues())
|
||||
{
|
||||
var attr = type.GetField(value.ToString())
|
||||
.GetCustomAttribute<DescriptionAttribute>();
|
||||
if (attr is null || exceptList.Contains(value)) continue;
|
||||
|
||||
var key = type.GetFields().FirstOrDefault(t=>t.Name== value.ToString()).GetRawConstantValue();
|
||||
dict[key] = attr.Description;
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
/// <summary>
|
||||
/// 大文件操作扩展类
|
||||
/// </summary>
|
||||
public static class FileExt
|
||||
{
|
||||
/// <summary>
|
||||
/// 以文件流的形式复制大文件
|
||||
/// </summary>
|
||||
/// <param name="fs">源</param>
|
||||
/// <param name="dest">目标地址</param>
|
||||
/// <param name="bufferSize">缓冲区大小,默认8MB</param>
|
||||
public static void CopyToFile(this Stream fs, string dest, int bufferSize = 1024 * 8 * 1024)
|
||||
{
|
||||
using var fsWrite = new FileStream(dest, FileMode.OpenOrCreate, FileAccess.ReadWrite);
|
||||
byte[] buf = new byte[bufferSize];
|
||||
int len;
|
||||
while ((len = fs.Read(buf, 0, buf.Length)) != 0)
|
||||
{
|
||||
fsWrite.Write(buf, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 以文件流的形式复制大文件(异步方式)
|
||||
/// </summary>
|
||||
/// <param name="fs">源</param>
|
||||
/// <param name="dest">目标地址</param>
|
||||
/// <param name="bufferSize">缓冲区大小,默认8MB</param>
|
||||
public static async void CopyToFileAsync(this Stream fs, string dest, int bufferSize = 1024 * 1024 * 8)
|
||||
{
|
||||
using var fsWrite = new FileStream(dest, FileMode.OpenOrCreate, FileAccess.ReadWrite);
|
||||
byte[] buf = new byte[bufferSize];
|
||||
int len;
|
||||
await Task.Run(() =>
|
||||
{
|
||||
while ((len = fs.Read(buf, 0, buf.Length)) != 0)
|
||||
{
|
||||
fsWrite.Write(buf, 0, len);
|
||||
}
|
||||
}).ConfigureAwait(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将内存流转储成文件
|
||||
/// </summary>
|
||||
/// <param name="ms"></param>
|
||||
/// <param name="filename"></param>
|
||||
public static void SaveFile(this MemoryStream ms, string filename)
|
||||
{
|
||||
using var fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
|
||||
byte[] buffer = ms.ToArray(); // 转化为byte格式存储
|
||||
fs.Write(buffer, 0, buffer.Length);
|
||||
fs.Flush();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
public static class IDictionaryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 添加或更新键值对
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="that">另一个字典集</param>
|
||||
/// <returns></returns>
|
||||
public static void AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
|
||||
{
|
||||
foreach (var item in that)
|
||||
{
|
||||
@this[item.Key] = item.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新键值对
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="that">另一个字典集</param>
|
||||
/// <returns></returns>
|
||||
public static void AddOrUpdateTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that)
|
||||
{
|
||||
foreach (var item in @this)
|
||||
{
|
||||
that[item.Key] = item.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新键值对
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="key">键</param>
|
||||
/// <param name="addValue">添加时的值</param>
|
||||
/// <param name="updateValueFactory">更新时的操作</param>
|
||||
/// <returns></returns>
|
||||
public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
|
||||
{
|
||||
if (!@this.ContainsKey(key))
|
||||
{
|
||||
@this.Add(key, addValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
@this[key] = updateValueFactory(key, @this[key]);
|
||||
}
|
||||
|
||||
return @this[key];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新键值对
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="key">键</param>
|
||||
/// <param name="addValue">添加时的值</param>
|
||||
/// <param name="updateValueFactory">更新时的操作</param>
|
||||
/// <returns></returns>
|
||||
public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, TValue addValue, Func<TKey, TValue, Task<TValue>> updateValueFactory)
|
||||
{
|
||||
if (!@this.ContainsKey(key))
|
||||
{
|
||||
@this.Add(key, addValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
@this[key] = await updateValueFactory(key, @this[key]);
|
||||
}
|
||||
|
||||
return @this[key];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新键值对
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="key">键</param>
|
||||
/// <param name="addValue">添加时的值</param>
|
||||
/// <param name="updateValue">更新时的值</param>
|
||||
/// <returns></returns>
|
||||
public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, TValue addValue, TValue updateValue)
|
||||
{
|
||||
if (!@this.ContainsKey(key))
|
||||
{
|
||||
@this.Add(key, addValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
@this[key] = updateValue;
|
||||
}
|
||||
|
||||
return @this[key];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新键值对
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="that">另一个字典集</param>
|
||||
/// <param name="updateValueFactory">更新时的操作</param>
|
||||
/// <returns></returns>
|
||||
public static void AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
|
||||
{
|
||||
foreach (var item in that)
|
||||
{
|
||||
AddOrUpdate(@this, item.Key, item.Value, updateValueFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新键值对
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="that">另一个字典集</param>
|
||||
/// <param name="updateValueFactory">更新时的操作</param>
|
||||
/// <returns></returns>
|
||||
public static Task AddOrUpdateAsync<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
|
||||
{
|
||||
return that.ForeachAsync(item => AddOrUpdateAsync(@this, item.Key, item.Value, updateValueFactory));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新键值对
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="that">另一个字典集</param>
|
||||
/// <param name="updateValueFactory">更新时的操作</param>
|
||||
/// <returns></returns>
|
||||
public static void AddOrUpdateTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, TValue> updateValueFactory)
|
||||
{
|
||||
foreach (var item in @this)
|
||||
{
|
||||
AddOrUpdate(that, item.Key, item.Value, updateValueFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新键值对
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="that">另一个字典集</param>
|
||||
/// <param name="updateValueFactory">更新时的操作</param>
|
||||
/// <returns></returns>
|
||||
public static Task AddOrUpdateAsyncTo<TKey, TValue>(this IDictionary<TKey, TValue> @this, IDictionary<TKey, TValue> that, Func<TKey, TValue, Task<TValue>> updateValueFactory)
|
||||
{
|
||||
return @this.ForeachAsync(item => AddOrUpdateAsync(that, item.Key, item.Value, updateValueFactory));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新键值对
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="key">键</param>
|
||||
/// <param name="addValueFactory">添加时的操作</param>
|
||||
/// <param name="updateValueFactory">更新时的操作</param>
|
||||
/// <returns></returns>
|
||||
public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
|
||||
{
|
||||
if (!@this.ContainsKey(key))
|
||||
{
|
||||
@this.Add(key, addValueFactory(key));
|
||||
}
|
||||
else
|
||||
{
|
||||
@this[key] = updateValueFactory(key, @this[key]);
|
||||
}
|
||||
|
||||
return @this[key];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加或更新键值对
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="key">键</param>
|
||||
/// <param name="addValueFactory">添加时的操作</param>
|
||||
/// <param name="updateValueFactory">更新时的操作</param>
|
||||
/// <returns></returns>
|
||||
public static async Task<TValue> AddOrUpdateAsync<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, Func<TKey, Task<TValue>> addValueFactory, Func<TKey, TValue, Task<TValue>> updateValueFactory)
|
||||
{
|
||||
if (!@this.ContainsKey(key))
|
||||
{
|
||||
@this.Add(key, await addValueFactory(key));
|
||||
}
|
||||
else
|
||||
{
|
||||
@this[key] = await updateValueFactory(key, @this[key]);
|
||||
}
|
||||
|
||||
return @this[key];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或添加
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="addValueFactory"></param>
|
||||
/// <returns></returns>
|
||||
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, Func<TValue> addValueFactory)
|
||||
{
|
||||
if (!@this.ContainsKey(key))
|
||||
{
|
||||
@this.Add(key, addValueFactory());
|
||||
}
|
||||
|
||||
return @this[key];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或添加
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="addValueFactory"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<TValue> GetOrAddAsync<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, Func<Task<TValue>> addValueFactory)
|
||||
{
|
||||
if (!@this.ContainsKey(key))
|
||||
{
|
||||
@this.Add(key, await addValueFactory());
|
||||
}
|
||||
|
||||
return @this[key];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或添加
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="addValue"></param>
|
||||
/// <returns></returns>
|
||||
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> @this, TKey key, TValue addValue)
|
||||
{
|
||||
if (!@this.ContainsKey(key))
|
||||
{
|
||||
@this.Add(key, addValue);
|
||||
}
|
||||
|
||||
return @this[key];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 遍历IEnumerable
|
||||
/// </summary>
|
||||
/// <param name="dic"></param>
|
||||
/// <param name="action">回调方法</param>
|
||||
public static void ForEach<TKey, TValue>(this IDictionary<TKey, TValue> dic, Action<TKey, TValue> action)
|
||||
{
|
||||
foreach (var item in dic)
|
||||
{
|
||||
action(item.Key, item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 遍历IDictionary
|
||||
/// </summary>
|
||||
/// <param name="dic"></param>
|
||||
/// <param name="action">回调方法</param>
|
||||
public static Task ForEachAsync<TKey, TValue>(this IDictionary<TKey, TValue> dic, Func<TKey, TValue, Task> action)
|
||||
{
|
||||
return dic.ForeachAsync(x => action(x.Key, x.Value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的转换成字典集
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="keySelector">键选择器</param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<TKey, TSource> ToDictionarySafety<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
|
||||
{
|
||||
var dic = new Dictionary<TKey, TSource>();
|
||||
foreach (var item in source)
|
||||
{
|
||||
dic[keySelector(item)] = item;
|
||||
}
|
||||
|
||||
return dic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的转换成字典集
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TElement"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="keySelector">键选择器</param>
|
||||
/// <param name="elementSelector">值选择器</param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<TKey, TElement> ToDictionarySafety<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
|
||||
{
|
||||
var dic = new Dictionary<TKey, TElement>();
|
||||
foreach (var item in source)
|
||||
{
|
||||
dic[keySelector(item)] = elementSelector(item);
|
||||
}
|
||||
|
||||
return dic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的转换成字典集
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TElement"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="keySelector">键选择器</param>
|
||||
/// <param name="elementSelector">值选择器</param>
|
||||
/// <returns></returns>
|
||||
public static async Task<IDictionary<TKey, TElement>> ToDictionarySafetyAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector)
|
||||
{
|
||||
var dic = new ConcurrentDictionary<TKey, TElement>();
|
||||
await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
|
||||
return dic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的转换成字典集
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TElement"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="keySelector">键选择器</param>
|
||||
/// <returns></returns>
|
||||
public static ConcurrentDictionary<TKey, TSource> ToConcurrentDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
|
||||
{
|
||||
var dic = new ConcurrentDictionary<TKey, TSource>();
|
||||
foreach (var item in source)
|
||||
{
|
||||
dic[keySelector(item)] = item;
|
||||
}
|
||||
|
||||
return dic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的转换成字典集
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TElement"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="keySelector">键选择器</param>
|
||||
/// <param name="elementSelector">值选择器</param>
|
||||
/// <returns></returns>
|
||||
public static ConcurrentDictionary<TKey, TElement> ToConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
|
||||
{
|
||||
var dic = new ConcurrentDictionary<TKey, TElement>();
|
||||
foreach (var item in source)
|
||||
{
|
||||
dic[keySelector(item)] = elementSelector(item);
|
||||
}
|
||||
|
||||
return dic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的转换成字典集
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TElement"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="keySelector">键选择器</param>
|
||||
/// <param name="elementSelector">值选择器</param>
|
||||
/// <returns></returns>
|
||||
public static async Task<ConcurrentDictionary<TKey, TElement>> ToConcurrentDictionaryAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector)
|
||||
{
|
||||
var dic = new ConcurrentDictionary<TKey, TElement>();
|
||||
await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
|
||||
return dic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换成并发字典集合
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="dic"></param>
|
||||
/// <returns></returns>
|
||||
public static ConcurrentDictionary<TKey, TValue> AsConcurrentDictionary<TKey, TValue>(this Dictionary<TKey, TValue> dic) => new(dic);
|
||||
|
||||
/// <summary>
|
||||
/// 转换成普通字典集合
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="dic"></param>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<TKey, TValue> AsDictionary<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dic) => new(dic);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,600 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
public static partial class IEnumerableExtensions
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 按字段去重
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TKey"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="keySelector"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
|
||||
{
|
||||
var hash = new HashSet<TKey>();
|
||||
return source.Where(p => hash.Add(keySelector(p)));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 添加多个元素
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="values"></param>
|
||||
public static void AddRange<T>(this ICollection<T> @this, params T[] values)
|
||||
{
|
||||
foreach (var obj in values)
|
||||
{
|
||||
@this.Add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加符合条件的多个元素
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="predicate"></param>
|
||||
/// <param name="values"></param>
|
||||
public static void AddRangeIf<T>(this ICollection<T> @this, Func<T, bool> predicate, params T[] values)
|
||||
{
|
||||
foreach (var obj in values)
|
||||
{
|
||||
if (predicate(obj))
|
||||
{
|
||||
@this.Add(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加不重复的元素
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="values"></param>
|
||||
public static void AddRangeIfNotContains<T>(this ICollection<T> @this, params T[] values)
|
||||
{
|
||||
foreach (T obj in values)
|
||||
{
|
||||
if (!@this.Contains(obj))
|
||||
{
|
||||
@this.Add(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除符合条件的元素
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="this"></param>
|
||||
/// <param name="where"></param>
|
||||
public static void RemoveWhere<T>(this ICollection<T> @this, Func<T, bool> @where)
|
||||
{
|
||||
foreach (var obj in @this.Where(where).ToList())
|
||||
{
|
||||
@this.Remove(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在元素之后添加元素
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="condition">条件</param>
|
||||
/// <param name="value">值</param>
|
||||
public static void InsertAfter<T>(this IList<T> list, Func<T, bool> condition, T value)
|
||||
{
|
||||
foreach (var item in list.Select((item, index) => new { item, index }).Where(p => condition(p.item)).OrderByDescending(p => p.index))
|
||||
{
|
||||
if (item.index + 1 == list.Count)
|
||||
{
|
||||
list.Add(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Insert(item.index + 1, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在元素之后添加元素
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="index">索引位置</param>
|
||||
/// <param name="value">值</param>
|
||||
public static void InsertAfter<T>(this IList<T> list, int index, T value)
|
||||
{
|
||||
foreach (var item in list.Select((v, i) => new { Value = v, Index = i }).Where(p => p.Index == index).OrderByDescending(p => p.Index))
|
||||
{
|
||||
if (item.Index + 1 == list.Count)
|
||||
{
|
||||
list.Add(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Insert(item.Index + 1, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转HashSet
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <returns></returns>
|
||||
public static HashSet<TResult> ToHashSet<T, TResult>(this IEnumerable<T> source, Func<T, TResult> selector)
|
||||
{
|
||||
var set = new HashSet<TResult>();
|
||||
set.UnionWith(source.Select(selector));
|
||||
return set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 遍历IEnumerable
|
||||
/// </summary>
|
||||
/// <param name="objs"></param>
|
||||
/// <param name="action">回调方法</param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public static void ForEach<T>(this IEnumerable<T> objs, Action<T> action)
|
||||
{
|
||||
foreach (var o in objs)
|
||||
{
|
||||
action(o);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步foreach
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="maxParallelCount">最大并行数</param>
|
||||
/// <param name="action"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task ForeachAsync<T>(this IEnumerable<T> source, Func<T, Task> action, int maxParallelCount, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var list = new List<Task>();
|
||||
foreach (var item in source)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
list.Add(action(item));
|
||||
if (list.Count >= maxParallelCount)
|
||||
{
|
||||
await Task.WhenAll(list);
|
||||
list.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(list);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步foreach
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="action"></param>
|
||||
/// <returns></returns>
|
||||
public static Task ForeachAsync<T>(this IEnumerable<T> source, Func<T, Task> action, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return ForeachAsync(source, action, source.Count(), cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步Select
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <returns></returns>
|
||||
public static Task<TResult[]> SelectAsync<T, TResult>(this IEnumerable<T> source, Func<T, Task<TResult>> selector)
|
||||
{
|
||||
return Task.WhenAll(source.Select(selector));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步Select
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <returns></returns>
|
||||
public static Task<TResult[]> SelectAsync<T, TResult>(this IEnumerable<T> source, Func<T, int, Task<TResult>> selector)
|
||||
{
|
||||
return Task.WhenAll(source.Select(selector));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步For
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <param name="maxParallelCount">最大并行数</param>
|
||||
/// <param name="cancellationToken">取消口令</param>
|
||||
/// <returns></returns>
|
||||
public static async Task ForAsync<T>(this IEnumerable<T> source, Func<T, int, Task> selector, int maxParallelCount, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var list = new List<Task>();
|
||||
int index = 0;
|
||||
foreach (var item in source)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
list.Add(selector(item, index++));
|
||||
if (list.Count >= maxParallelCount)
|
||||
{
|
||||
await Task.WhenAll(list);
|
||||
list.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(list);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步For
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <param name="cancellationToken">取消口令</param>
|
||||
/// <returns></returns>
|
||||
public static Task ForAsync<T>(this IEnumerable<T> source, Func<T, int, Task> selector, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return ForAsync(source, selector, source.Count(), cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取最大值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <returns></returns>
|
||||
public static TResult MaxOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector)
|
||||
=> source.Select(selector).DefaultIfEmpty().Max();
|
||||
|
||||
/// <summary>
|
||||
/// 取最大值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static TResult MaxOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TResult defaultValue) => source.Select(selector).DefaultIfEmpty(defaultValue).Max();
|
||||
|
||||
/// <summary>
|
||||
/// 取最大值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static TSource MaxOrDefault<TSource>(this IQueryable<TSource> source) => source.DefaultIfEmpty().Max();
|
||||
|
||||
/// <summary>
|
||||
/// 取最大值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static TSource MaxOrDefault<TSource>(this IQueryable<TSource> source, TSource defaultValue) => source.DefaultIfEmpty(defaultValue).Max();
|
||||
|
||||
/// <summary>
|
||||
/// 取最大值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static TResult MaxOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector, TResult defaultValue) => source.Select(selector).DefaultIfEmpty(defaultValue).Max();
|
||||
|
||||
/// <summary>
|
||||
/// 取最大值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <returns></returns>
|
||||
public static TResult MaxOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) => source.Select(selector).DefaultIfEmpty().Max();
|
||||
|
||||
/// <summary>
|
||||
/// 取最大值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static TSource MaxOrDefault<TSource>(this IEnumerable<TSource> source) => source.DefaultIfEmpty().Max();
|
||||
|
||||
/// <summary>
|
||||
/// 取最大值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static TSource MaxOrDefault<TSource>(this IEnumerable<TSource> source, TSource defaultValue) => source.DefaultIfEmpty(defaultValue).Max();
|
||||
|
||||
/// <summary>
|
||||
/// 取最小值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <returns></returns>
|
||||
public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector) => source.Select(selector).DefaultIfEmpty().Min();
|
||||
|
||||
/// <summary>
|
||||
/// 取最小值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static TResult MinOrDefault<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector, TResult defaultValue) => source.Select(selector).DefaultIfEmpty(defaultValue).Min();
|
||||
|
||||
/// <summary>
|
||||
/// 取最小值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source) => source.DefaultIfEmpty().Min();
|
||||
|
||||
/// <summary>
|
||||
/// 取最小值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static TSource MinOrDefault<TSource>(this IQueryable<TSource> source, TSource defaultValue) => source.DefaultIfEmpty(defaultValue).Min();
|
||||
|
||||
/// <summary>
|
||||
/// 取最小值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <returns></returns>
|
||||
public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) => source.Select(selector).DefaultIfEmpty().Min();
|
||||
|
||||
/// <summary>
|
||||
/// 取最小值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector, TResult defaultValue) => source.Select(selector).DefaultIfEmpty(defaultValue).Min();
|
||||
|
||||
/// <summary>
|
||||
/// 取最小值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source) => source.DefaultIfEmpty().Min();
|
||||
|
||||
/// <summary>
|
||||
/// 取最小值
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static TSource MinOrDefault<TSource>(this IEnumerable<TSource> source, TSource defaultValue) => source.DefaultIfEmpty(defaultValue).Min();
|
||||
|
||||
///// <summary>
|
||||
///// 标准差
|
||||
///// </summary>
|
||||
///// <typeparam name="T"></typeparam>
|
||||
///// <param name="source"></param>
|
||||
///// <param name="selector"></param>
|
||||
///// <returns></returns>
|
||||
//public static TResult StandardDeviation<T, TResult>(this IEnumerable<T> source, Func<T, TResult> selector) where TResult : IConvertible
|
||||
//{
|
||||
// return StandardDeviation(source.Select(t => selector(t).ConvertTo<double>())).ConvertTo<TResult>();
|
||||
//}
|
||||
|
||||
///// <summary>
|
||||
///// 标准差
|
||||
///// </summary>
|
||||
///// <typeparam name="T"></typeparam>
|
||||
///// <param name="source"></param>
|
||||
///// <returns></returns>
|
||||
//public static T StandardDeviation<T>(this IEnumerable<T> source) where T : IConvertible
|
||||
//{
|
||||
// return StandardDeviation(source.Select(t => t.ConvertTo<double>())).ConvertTo<T>();
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// 标准差
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static double StandardDeviation(this IEnumerable<double> source)
|
||||
{
|
||||
double result = 0;
|
||||
int count = source.Count();
|
||||
if (count > 1)
|
||||
{
|
||||
double avg = source.Average();
|
||||
double sum = source.Sum(d => (d - avg) * (d - avg));
|
||||
result = Math.Sqrt(sum / count);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 随机排序
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static IOrderedEnumerable<T> OrderByRandom<T>(this IEnumerable<T> source)
|
||||
{
|
||||
return source.OrderBy(_ => Guid.NewGuid());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列相等
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="first"></param>
|
||||
/// <param name="second"></param>
|
||||
/// <param name="condition"></param>
|
||||
/// <returns></returns>
|
||||
public static bool SequenceEqual<T>(this IEnumerable<T> first, IEnumerable<T> second, Func<T, T, bool> condition)
|
||||
{
|
||||
if (first is ICollection<T> source1 && second is ICollection<T> source2)
|
||||
{
|
||||
if (source1.Count != source2.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (source1 is IList<T> list1 && source2 is IList<T> list2)
|
||||
{
|
||||
int count = source1.Count;
|
||||
for (int index = 0; index < count; ++index)
|
||||
{
|
||||
if (!condition(list1[index], list2[index]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
using IEnumerator<T> enumerator1 = first.GetEnumerator();
|
||||
using IEnumerator<T> enumerator2 = second.GetEnumerator();
|
||||
while (enumerator1.MoveNext())
|
||||
{
|
||||
if (!enumerator2.MoveNext() || !condition(enumerator1.Current, enumerator2.Current))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !enumerator2.MoveNext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列相等
|
||||
/// </summary>
|
||||
/// <typeparam name="T1"></typeparam>
|
||||
/// <typeparam name="T2"></typeparam>
|
||||
/// <param name="first"></param>
|
||||
/// <param name="second"></param>
|
||||
/// <param name="condition"></param>
|
||||
/// <returns></returns>
|
||||
public static bool SequenceEqual<T1, T2>(this IEnumerable<T1> first, IEnumerable<T2> second, Func<T1, T2, bool> condition)
|
||||
{
|
||||
if (first is ICollection<T1> source1 && second is ICollection<T2> source2)
|
||||
{
|
||||
if (source1.Count != source2.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (source1 is IList<T1> list1 && source2 is IList<T2> list2)
|
||||
{
|
||||
int count = source1.Count;
|
||||
for (int index = 0; index < count; ++index)
|
||||
{
|
||||
if (!condition(list1[index], list2[index]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
using IEnumerator<T1> enumerator1 = first.GetEnumerator();
|
||||
using IEnumerator<T2> enumerator2 = second.GetEnumerator();
|
||||
while (enumerator1.MoveNext())
|
||||
{
|
||||
if (!enumerator2.MoveNext() || !condition(enumerator1.Current, enumerator2.Current))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !enumerator2.MoveNext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对比两个集合哪些是新增的、删除的、修改的
|
||||
/// </summary>
|
||||
/// <typeparam name="T1"></typeparam>
|
||||
/// <typeparam name="T2"></typeparam>
|
||||
/// <param name="olds"></param>
|
||||
/// <param name="news"></param>
|
||||
/// <param name="key1Selector">对比因素属性</param>
|
||||
/// <param name="key2Selector">对比因素属性</param>
|
||||
/// <returns></returns>
|
||||
public static (List<T2> adds, List<T1> remove, List<T1> updates) CompareChanges<T1, T2>(this IEnumerable<T1> olds, IEnumerable<T2> news, Func<T1, object> key1Selector, Func<T2, object> key2Selector)
|
||||
{
|
||||
return (news.Where(c => olds.All(m => key1Selector(m) != key2Selector(c))).ToList(), olds.Where(m => news.All(c => key2Selector(c) != key1Selector(m))).ToList(), olds.Where(m => news.Any(c => key1Selector(m) == key2Selector(c))).ToList());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对比两个集合哪些是新增的、删除的、修改的
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="olds"></param>
|
||||
/// <param name="news"></param>
|
||||
/// <param name="keySelector">对比因素属性</param>
|
||||
/// <returns></returns>
|
||||
public static (List<T> adds, List<T> remove, List<T> updates) CompareChanges<T>(this IEnumerable<T> olds, IEnumerable<T> news, Func<T, object> keySelector)
|
||||
{
|
||||
return (news.Where(c => olds.All(m => keySelector(m) != keySelector(c))).ToList(), olds.Where(m => news.All(c => keySelector(c) != keySelector(m))).ToList(), olds.Where(m => news.Any(c => keySelector(m) == keySelector(c))).ToList());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq.Dynamic.Core;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
public static class QueryablePageListExtensions
|
||||
{
|
||||
//单字段排序
|
||||
public static PageOutput<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize, string defaultSortFiled = "Id", bool isAsc = true)
|
||||
{
|
||||
if (pageIndex <= 0)
|
||||
{
|
||||
pageIndex = 1;
|
||||
}
|
||||
if (pageSize <= 0)
|
||||
{
|
||||
pageSize = 10;
|
||||
}
|
||||
var count = source.Count();
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
return new PageOutput<T>() { CurrentPageData=new T[0] };
|
||||
}
|
||||
|
||||
|
||||
var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
|
||||
|
||||
source = isAsc ? source.OrderBy(propName) : source.OrderBy(propName + " desc");
|
||||
|
||||
source = source.Skip((pageIndex - 1) * pageSize);
|
||||
|
||||
var items = source
|
||||
.Take(pageSize)
|
||||
.ToArray();
|
||||
|
||||
var pagedList = new PageOutput<T>()
|
||||
{
|
||||
PageIndex = pageIndex,
|
||||
PageSize = pageSize,
|
||||
TotalCount = count,
|
||||
CurrentPageData = items
|
||||
};
|
||||
|
||||
return pagedList;
|
||||
}
|
||||
|
||||
//单字段排序 异步
|
||||
public static async Task<PageOutput<T>> ToPagedListAsync<T>(this IQueryable<T> source, int pageNumber, int pageSize, string defaultSortFiled = "Id", bool isAsc = true,bool isMultiSortFiled=false, string[] sortArray=default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
|
||||
if (isMultiSortFiled&& sortArray==default)
|
||||
{
|
||||
throw new System.Exception("必须指定排序字段");
|
||||
}
|
||||
|
||||
if (pageNumber <= 0)
|
||||
{
|
||||
pageNumber = 1;
|
||||
}
|
||||
if (pageSize <= 0)
|
||||
{
|
||||
pageSize = 10;
|
||||
}
|
||||
|
||||
var count = await source.CountAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
return new PageOutput<T>() { CurrentPageData = new T[0] };
|
||||
}
|
||||
var propName = string.IsNullOrWhiteSpace(defaultSortFiled) ? "Id" : defaultSortFiled;
|
||||
|
||||
if (!isMultiSortFiled)
|
||||
{
|
||||
source = isAsc ? source.OrderBy(propName) : source.OrderBy(propName + " desc");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var sortString = string.Join(',', sortArray);
|
||||
|
||||
source= source.OrderBy(sortString);
|
||||
}
|
||||
source = source.Skip((pageNumber - 1) * pageSize);
|
||||
var items = await source
|
||||
.Take(pageSize)
|
||||
.ToArrayAsync(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var pagedList = new PageOutput<T>()
|
||||
{
|
||||
PageIndex = pageNumber,
|
||||
PageSize = pageSize,
|
||||
TotalCount = count,
|
||||
CurrentPageData = items
|
||||
};
|
||||
|
||||
return pagedList;
|
||||
}
|
||||
|
||||
//多字段排序 ["a asc", "b desc", "c asc"]
|
||||
public static PageOutput<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize,string[] sortArray)
|
||||
{
|
||||
if (pageIndex <= 0)
|
||||
{
|
||||
pageIndex = 1;
|
||||
}
|
||||
if (pageSize <= 0)
|
||||
{
|
||||
pageSize = 10;
|
||||
}
|
||||
var count = source.Count();
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
return new PageOutput<T>() { CurrentPageData = new T[0] };
|
||||
}
|
||||
|
||||
var sortString = string.Join(',', sortArray);
|
||||
|
||||
source.OrderBy(sortString);
|
||||
|
||||
source = source.Skip((pageIndex - 1) * pageSize);
|
||||
|
||||
var items = source
|
||||
.Take(pageSize)
|
||||
.ToArray();
|
||||
|
||||
var pagedList = new PageOutput<T>()
|
||||
{
|
||||
PageIndex = pageIndex,
|
||||
PageSize = pageSize,
|
||||
TotalCount = count,
|
||||
CurrentPageData = items
|
||||
};
|
||||
|
||||
return pagedList;
|
||||
}
|
||||
|
||||
//多字段排序异步 ["a asc", "b desc", "c asc"]
|
||||
public static async Task<PageOutput<T>> ToPagedListAsync<T>(this IQueryable<T> source, int pageNumber, int pageSize, string[] sortArray, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (pageNumber <= 0)
|
||||
{
|
||||
pageNumber = 1;
|
||||
}
|
||||
if (pageSize <= 0)
|
||||
{
|
||||
pageSize = 10;
|
||||
}
|
||||
|
||||
var count = await source.CountAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
return new PageOutput<T>() { CurrentPageData = new T[0] };
|
||||
}
|
||||
|
||||
var sortString = string.Join(',', sortArray);
|
||||
|
||||
source = source.OrderBy(sortString);
|
||||
|
||||
source = source.Skip((pageNumber - 1) * pageSize);
|
||||
var items = await source
|
||||
.Take(pageSize)
|
||||
.ToArrayAsync(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var pagedList = new PageOutput<T>()
|
||||
{
|
||||
PageIndex = pageNumber,
|
||||
PageSize = pageSize,
|
||||
TotalCount = count,
|
||||
CurrentPageData = items
|
||||
};
|
||||
|
||||
return pagedList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
public static class QueryableWhereExtension
|
||||
{
|
||||
public static IQueryable<TEntity> WhereIf<TEntity>(this IQueryable<TEntity> query, [NotNullWhen(true)] bool condition, Expression<Func<TEntity, bool>> filter) where TEntity : class
|
||||
{
|
||||
return condition ? query.Where(filter) : query;
|
||||
}
|
||||
|
||||
public static IEnumerable<TEntity> WhereIf<TEntity>(this IEnumerable<TEntity> query, bool condition, Func<TEntity, bool> filter) where TEntity : class
|
||||
{
|
||||
return condition ? query.Where(filter) : query;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
/// <summary>
|
||||
/// 分页信息输入
|
||||
/// </summary>
|
||||
public class PageInput
|
||||
{
|
||||
public int PageIndex { get; set; } = 1;
|
||||
public int PageSize { set; get; } = 10;
|
||||
public bool Asc { get; set; } = true;
|
||||
public string SortField { get; set; } = "";
|
||||
}
|
||||
|
||||
public class PageInputMultiSort
|
||||
{
|
||||
public int PageIndex { get; set; } = 1;
|
||||
public int PageSize { set; get; } = 10;
|
||||
|
||||
//["a asc", "b desc", "c asc"]
|
||||
public string[] SortArray { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
/// <summary>
|
||||
/// LINQ扩展方法
|
||||
/// </summary>
|
||||
public static class LinqExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 与连接
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
/// <param name="left">左条件</param>
|
||||
/// <param name="right">右条件</param>
|
||||
/// <returns>新表达式</returns>
|
||||
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
|
||||
{
|
||||
return CombineLambdas(left, right, ExpressionType.AndAlso);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 或连接
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
/// <param name="left">左条件</param>
|
||||
/// <param name="right">右条件</param>
|
||||
/// <returns>新表达式</returns>
|
||||
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
|
||||
{
|
||||
return CombineLambdas(left, right, ExpressionType.OrElse);
|
||||
}
|
||||
|
||||
private static Expression<Func<T, bool>> CombineLambdas<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right, ExpressionType expressionType)
|
||||
{
|
||||
var visitor = new SubstituteParameterVisitor
|
||||
{
|
||||
Sub =
|
||||
{
|
||||
[right.Parameters[0]] = left.Parameters[0]
|
||||
}
|
||||
};
|
||||
|
||||
Expression body = Expression.MakeBinary(expressionType, left.Body, visitor.Visit(right.Body));
|
||||
return Expression.Lambda<Func<T, bool>>(body, left.Parameters[0]);
|
||||
}
|
||||
}
|
||||
|
||||
internal class SubstituteParameterVisitor : ExpressionVisitor
|
||||
{
|
||||
public Dictionary<Expression, Expression> Sub = new Dictionary<Expression, Expression>();
|
||||
|
||||
protected override Expression VisitParameter(ParameterExpression node)
|
||||
{
|
||||
return Sub.TryGetValue(node, out var newValue) ? newValue : node;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
public static class ListExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 将列表转换为树形结构
|
||||
/// </summary>
|
||||
/// <typeparam name="T">类型</typeparam>
|
||||
/// <param name="list">数据</param>
|
||||
/// <param name="rootWhere">根条件</param>
|
||||
/// <param name="childsWhere">节点条件</param>
|
||||
/// <param name="addChilds">添加子节点</param>
|
||||
/// <param name="childEntity"></param>
|
||||
/// <returns></returns>
|
||||
public static List<T> ToTree<T,Tkey>(this List<T> list, Func<T, T, bool> rootWhere, Func<T, T, bool> childsWhere, Action<T, IEnumerable<T>> addChilds, Func<T, Tkey> orderSelector, T childEntity = default)
|
||||
{
|
||||
if (rootWhere is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(rootWhere));
|
||||
}
|
||||
|
||||
if (childsWhere is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(childsWhere));
|
||||
}
|
||||
|
||||
if (addChilds is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(addChilds));
|
||||
}
|
||||
|
||||
if (orderSelector is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(orderSelector));
|
||||
}
|
||||
|
||||
var treelist = new List<T>();
|
||||
//空树
|
||||
if (list == null || list.Count == 0)
|
||||
{
|
||||
return treelist;
|
||||
}
|
||||
if (!list.Any(e => rootWhere(childEntity, e)))
|
||||
{
|
||||
return treelist;
|
||||
}
|
||||
//树根
|
||||
if (list.Any(e => rootWhere(childEntity, e)))
|
||||
{
|
||||
treelist.AddRange(list.Where(e => rootWhere(childEntity, e)).OrderBy(orderSelector));
|
||||
}
|
||||
//树叶 item 是根
|
||||
foreach (var item in treelist)
|
||||
{
|
||||
if (list.Any(e => childsWhere(item, e)))
|
||||
{
|
||||
var nodedata = list.Where(e => childsWhere(item, e)).OrderBy(orderSelector).ToList();
|
||||
|
||||
foreach (var child in nodedata)
|
||||
{
|
||||
//添加子集
|
||||
var data = list.ToTree(childsWhere, childsWhere, addChilds, orderSelector, child);
|
||||
|
||||
addChilds(child, data);
|
||||
}
|
||||
addChilds(item, nodedata);
|
||||
}
|
||||
}
|
||||
return treelist;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
/// <summary>
|
||||
/// 此处是为了 后续代替 IsSuccess IsSuccess暂时还是保留,接下来的接口判断现在用Code 判断 不用IsSuccess就好了
|
||||
|
||||
/// </summary>
|
||||
public enum ApiResponseCodeEnum
|
||||
{
|
||||
//正常的 相当于之前的 IsSuccess = true
|
||||
OK = 0,
|
||||
|
||||
//Api 输入参数有问题 相当于之前的 IsSuccess = false
|
||||
ApiInputError = 1,
|
||||
|
||||
//业务验证不通过 相当于之前的 IsSuccess = false
|
||||
BusinessValidationFailed = 2,
|
||||
|
||||
//数据不存在
|
||||
DataNotExist=3,
|
||||
|
||||
//程序异常 相当于之前的 IsSuccess = false
|
||||
ProgramException = 4,
|
||||
|
||||
//需要提示 ,需要提示 从Result 取数据
|
||||
NeedTips = 5
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
/// <summary>
|
||||
/// 响应数据输出接口
|
||||
/// </summary>
|
||||
public interface IResponseOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否成功
|
||||
/// </summary>
|
||||
bool IsSuccess { get; }
|
||||
|
||||
public ApiResponseCodeEnum Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 消息
|
||||
/// </summary>
|
||||
string ErrorMessage { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 响应数据输出泛型接口
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public interface IResponseOutput<T> : IResponseOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回数据
|
||||
/// </summary>
|
||||
T Data { get; }
|
||||
}
|
||||
|
||||
public interface IResponseOutput<T,T2> : IResponseOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回数据
|
||||
/// </summary>
|
||||
T Data { get; }
|
||||
|
||||
T2 OtherInfo { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
public static class NUllCheckExtension
|
||||
{
|
||||
|
||||
|
||||
[DoesNotReturn]
|
||||
public static TEntity IfNullThrowException<TEntity>(this TEntity businessObject) where TEntity : class
|
||||
{
|
||||
if(businessObject == null)
|
||||
{
|
||||
throw new QueryBusinessObjectNotExistException($"The query object {typeof(TEntity).Name} does not exist , or was deleted by someone else, or an incorrect parameter query caused");
|
||||
}
|
||||
else
|
||||
{
|
||||
return businessObject!;
|
||||
}
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
public static TEntity IfNullThrowException<TEntity>(this TEntity? businessStruct) where TEntity : struct
|
||||
{
|
||||
if (businessStruct == null)
|
||||
{
|
||||
throw new QueryBusinessObjectNotExistException($"The query object {typeof(TEntity).Name} does not exist , or was deleted by someone else, or an incorrect parameter query caused");
|
||||
}
|
||||
else
|
||||
{
|
||||
return (TEntity)businessStruct;
|
||||
}
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
public static TEntity IfNullThrowConvertException<TEntity>(this TEntity businessObject) where TEntity : class
|
||||
{
|
||||
if (businessObject == null)
|
||||
{
|
||||
throw new QueryBusinessObjectNotExistException($" Can not Convert to {typeof(TEntity).Name} Type, Please check parameter");
|
||||
}
|
||||
else
|
||||
{
|
||||
return businessObject!;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class QueryBusinessObjectNotExistException : Exception
|
||||
{
|
||||
|
||||
public QueryBusinessObjectNotExistException()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public QueryBusinessObjectNotExistException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class ConversionException : Exception
|
||||
{
|
||||
public ConversionException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
/// <summary>
|
||||
/// 分页信息输出 泛型
|
||||
/// </summary>
|
||||
public class PageOutput<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前页索引
|
||||
/// </summary>
|
||||
public int PageIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 每页的记录条数
|
||||
/// </summary>
|
||||
public int PageSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据总数
|
||||
/// </summary>
|
||||
public long TotalCount { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 数据
|
||||
/// </summary>
|
||||
public IList<T> CurrentPageData { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 分页数据 可能额外返回其他类型的查询数据 必须一些配置
|
||||
/// </summary>
|
||||
public object OtherData { get; set; }
|
||||
|
||||
public PageOutput()
|
||||
{
|
||||
}
|
||||
|
||||
public PageOutput(int pageIndex, int pageSize, long totalCount, IList<T> data)
|
||||
{
|
||||
PageIndex = pageIndex;
|
||||
PageSize = pageSize;
|
||||
TotalCount = totalCount;
|
||||
CurrentPageData = data;
|
||||
}
|
||||
|
||||
public PageOutput(int pageIndex, int pageSize, IQueryable<T> list)
|
||||
{
|
||||
PageIndex = pageIndex;
|
||||
PageSize = pageSize;
|
||||
TotalCount = list.Count();
|
||||
CurrentPageData = list.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
/// <summary>
|
||||
/// 响应数据输出 泛型
|
||||
/// </summary>
|
||||
public class ResponseOutput<T> : IResponseOutput<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否成功标记
|
||||
/// </summary>
|
||||
public bool IsSuccess { get; private set; }
|
||||
|
||||
|
||||
public ApiResponseCodeEnum Code { get; set; } = ApiResponseCodeEnum.OK;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 消息
|
||||
/// </summary>
|
||||
public string ErrorMessage { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据 兼顾以前 Json序列化的时候返回属性名为“Result”
|
||||
/// </summary>
|
||||
[JsonProperty("Result")]
|
||||
public T Data { get; private set; }
|
||||
|
||||
|
||||
|
||||
public object OtherData { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 成功
|
||||
/// </summary>
|
||||
/// <param name="data">数据</param>
|
||||
/// <param name="msg">消息</param>
|
||||
//public ResponseOutput<T> Ok(T data, string msg = "", ApiResponseCodeEnum code = ApiResponseCodeEnum.OK)
|
||||
//{
|
||||
// IsSuccess = true;
|
||||
// Code = code;
|
||||
// Data = data;
|
||||
// ErrorMessage = msg;
|
||||
|
||||
// return this;
|
||||
//}
|
||||
|
||||
public ResponseOutput<T> Ok(T data, object otherData, string msg = "", ApiResponseCodeEnum code = ApiResponseCodeEnum.OK)
|
||||
{
|
||||
IsSuccess = true;
|
||||
Code = code;
|
||||
Data = data;
|
||||
OtherData=otherData;
|
||||
ErrorMessage = msg;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 失败
|
||||
/// </summary>
|
||||
/// <param name="msg">提示消息</param>
|
||||
/// <param name="data">数据</param>
|
||||
/// <returns></returns>
|
||||
public ResponseOutput<T> NotOk(string msg = "", T data = default, ApiResponseCodeEnum code = ApiResponseCodeEnum.OK)
|
||||
{
|
||||
IsSuccess = false;
|
||||
Code = code;
|
||||
ErrorMessage = msg;
|
||||
Data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class ResponseOutput<T, T2> : IResponseOutput<T, T2>
|
||||
{
|
||||
[JsonProperty("Result")]
|
||||
public T Data { get; private set; }
|
||||
|
||||
public T2 OtherInfo { get; private set; }
|
||||
|
||||
public bool IsSuccess { get; private set; }
|
||||
|
||||
public ApiResponseCodeEnum Code { get; set; }
|
||||
|
||||
|
||||
public string ErrorMessage { get; private set; }
|
||||
|
||||
|
||||
public ResponseOutput<T, T2> Ok(T data, T2 otherInfo, string msg = "")
|
||||
{
|
||||
IsSuccess = true;
|
||||
Data = data;
|
||||
OtherInfo = otherInfo;
|
||||
ErrorMessage = msg;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 响应数据静态输出 为了代码简洁 不用每处都New
|
||||
/// </summary>
|
||||
public static class ResponseOutput
|
||||
{
|
||||
|
||||
|
||||
public static IResponseOutput<T, T2> Ok<T, T2>(T data, T2 otherInfo, string msg = "")
|
||||
{
|
||||
return new ResponseOutput<T, T2>().Ok(data, otherInfo);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 成功 -----适合查询
|
||||
/// </summary>
|
||||
/// <param name="data">数据</param>
|
||||
/// <param name="msg">消息</param>
|
||||
/// <returns></returns>
|
||||
//public static IResponseOutput<T> Ok<T>(T data = default, string msg = "")
|
||||
//{
|
||||
// return new ResponseOutput<T>().Ok(data, msg);
|
||||
//}
|
||||
|
||||
public static IResponseOutput<T> Ok<T>(T data = default, object otherData = default, string msg = "")
|
||||
{
|
||||
return new ResponseOutput<T>().Ok(data, otherData, msg);
|
||||
}
|
||||
/// <summary>
|
||||
/// 成功
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static IResponseOutput Ok()
|
||||
{
|
||||
return Ok<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 失败
|
||||
/// </summary>
|
||||
/// <param name="msg">消息</param>
|
||||
/// <param name="data">数据</param>
|
||||
/// <returns></returns>
|
||||
public static IResponseOutput<T> NotOk<T>(string msg = "", T data = default, ApiResponseCodeEnum code = ApiResponseCodeEnum.OK)
|
||||
{
|
||||
return new ResponseOutput<T>().NotOk(msg, data, code);
|
||||
}
|
||||
|
||||
public static IResponseOutput<T> NotOk<T>( T data = default, ApiResponseCodeEnum code = ApiResponseCodeEnum.OK)
|
||||
{
|
||||
return new ResponseOutput<T>().NotOk("", data, code);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 失败
|
||||
/// </summary>
|
||||
/// <param name="msg">消息</param>
|
||||
/// <returns></returns>
|
||||
public static IResponseOutput<string> NotOk(string msg = "", ApiResponseCodeEnum code = ApiResponseCodeEnum.OK)
|
||||
{
|
||||
return new ResponseOutput<string>().NotOk(msg,code:code);
|
||||
}
|
||||
|
||||
public static IResponseOutput<string> DBNotExistIfNUll(object businessObject)
|
||||
{
|
||||
return new ResponseOutput<string>().NotOk($"The business object{businessObject.GetType().Name} does not exist in the database, or was deleted by someone else, or an incorrect parameter query caused");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 根据布尔值返回结果 --适合删除
|
||||
/// </summary>
|
||||
/// <param name="success"></param>
|
||||
/// <returns></returns>
|
||||
public static IResponseOutput Result(bool success)
|
||||
{
|
||||
return success ? Ok() : NotOk("Expect a change, but the database data has not changed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据布尔值返回结果 --适合添加和更新一起
|
||||
/// </summary>
|
||||
/// <param name="success"></param>
|
||||
/// <returns></returns>
|
||||
public static IResponseOutput<T> Result<T>(bool success, T data = default)
|
||||
{
|
||||
return success ? Ok<T>(data) : NotOk<T>("Saved failed");
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// 根据布尔值返回结果
|
||||
///// </summary>
|
||||
///// <param name="success"></param>
|
||||
///// <returns></returns>
|
||||
//public static IResponseOutput Result<T>(bool success)
|
||||
//{
|
||||
// return success ? Ok<T>() : NotOk<T>();
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
public static class HttpContextExtension
|
||||
{
|
||||
|
||||
public static T GetService<T>(this HttpContext context) where T : class
|
||||
{
|
||||
return context.RequestServices.GetService(typeof(T)) as T;
|
||||
}
|
||||
|
||||
|
||||
public static string GetUserIp(this HttpContext context)
|
||||
{
|
||||
string realIP = null;
|
||||
string forwarded = null;
|
||||
string remoteIpAddress = context.Connection.RemoteIpAddress.ToString();
|
||||
if (context.Request.Headers.ContainsKey("X-Real-IP"))
|
||||
{
|
||||
realIP = context.Request.Headers["X-Real-IP"].ToString();
|
||||
if (realIP != remoteIpAddress)
|
||||
{
|
||||
remoteIpAddress = realIP;
|
||||
}
|
||||
}
|
||||
if (context.Request.Headers.ContainsKey("X-Forwarded-For"))
|
||||
{
|
||||
forwarded = context.Request.Headers["X-Forwarded-For"].ToString();
|
||||
if (forwarded != remoteIpAddress)
|
||||
{
|
||||
remoteIpAddress = forwarded;
|
||||
}
|
||||
}
|
||||
return remoteIpAddress;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取Request值
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="parameter"></param>
|
||||
/// <returns></returns>
|
||||
public static string Request(this HttpContext context, string parameter)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (context == null)
|
||||
return null;
|
||||
if (context.Request.Method == "POST")
|
||||
return context.Request.Form[parameter].ToString();
|
||||
else
|
||||
return context.Request.Query[parameter].ToString();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Console.Write(ex.Message + ex.InnerException);
|
||||
return context.RequestString(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
public static T Request<T>(this HttpContext context, string parameter) where T : class
|
||||
{
|
||||
return context.RequestString(parameter)?.DeserializeObject<T>();
|
||||
}
|
||||
public static string RequestString(this HttpContext context, string parameter)
|
||||
{
|
||||
string requestParam = context.GetRequestParameters();
|
||||
if (string.IsNullOrEmpty(requestParam)) return null;
|
||||
Dictionary<string, object> keyValues = requestParam.DeserializeObject<Dictionary<string, object>>();
|
||||
if (keyValues == null || keyValues.Count == 0) return null;
|
||||
if (keyValues.TryGetValue(parameter, out object value))
|
||||
{
|
||||
if (value == null) return null;
|
||||
if (value.GetType() == typeof(string))
|
||||
{
|
||||
return value?.ToString();
|
||||
}
|
||||
return value.Serialize();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否为ajax请求
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsAjaxRequest(this HttpContext context)
|
||||
{
|
||||
return context.Request("X-Requested-With") == "XMLHttpRequest"
|
||||
|| (context.Request.Headers != null
|
||||
&& context.Request.Headers["X-Requested-With"] == "XMLHttpRequest");
|
||||
}
|
||||
|
||||
public static UserAgent GetAgentType(this HttpContext context)
|
||||
{
|
||||
string agent = context.Request.Headers["User-Agent"].ToString().ToLower();
|
||||
|
||||
if (agent.Contains("ios") || agent.Contains("ipod") || agent.Contains("ipad"))
|
||||
{
|
||||
return UserAgent.IOS;
|
||||
}
|
||||
if (agent.Contains("windows"))
|
||||
{
|
||||
return UserAgent.Windows;
|
||||
}
|
||||
return UserAgent.Android;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取请求的参数
|
||||
/// net core 2.0已增加回读方法 context.Request.EnableRewind();
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
|
||||
public static string GetRequestParameters(this HttpContext context)
|
||||
{
|
||||
if (context.Request.Body == null || !context.Request.Body.CanRead || !context.Request.Body.CanSeek)
|
||||
return null;
|
||||
if (context.Request.Body.Length == 0)
|
||||
return null;
|
||||
if (context.Request.Body.Position > 0)
|
||||
context.Request.Body.Position = 0;
|
||||
|
||||
string prarameters = null;
|
||||
var bodyStream = context.Request.Body;
|
||||
|
||||
using (var buffer = new MemoryStream())
|
||||
{
|
||||
bodyStream.CopyToAsync(buffer);
|
||||
buffer.Position = 0L;
|
||||
bodyStream.Position = 0L;
|
||||
using (var reader = new StreamReader(buffer, Encoding.UTF8))
|
||||
{
|
||||
buffer.Seek(0, SeekOrigin.Begin);
|
||||
prarameters = reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
return prarameters;
|
||||
}
|
||||
}
|
||||
public enum UserAgent
|
||||
{
|
||||
IOS = 0,
|
||||
Android = 1,
|
||||
Windows = 2,
|
||||
Linux
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Writers;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace IRaCIS.Core.Infrastructure.Extention
|
||||
{
|
||||
/// <summary>
|
||||
/// 7z压缩
|
||||
/// </summary>
|
||||
public static class SevenZipCompressor
|
||||
{
|
||||
/// <summary>
|
||||
/// 将多个文件压缩到一个内存流中,可保存为zip文件,方便于web方式下载
|
||||
/// </summary>
|
||||
/// <param name="files">多个文件路径,文件或文件夹,或网络路径http/https</param>
|
||||
/// <param name="rootdir"></param>
|
||||
/// <returns>文件流</returns>
|
||||
public static MemoryStream ZipStream(List<string> files, string rootdir = "")
|
||||
{
|
||||
using var archive = CreateZipArchive(files, rootdir);
|
||||
var ms = new MemoryStream();
|
||||
archive.SaveTo(ms, new WriterOptions(CompressionType.Deflate)
|
||||
{
|
||||
LeaveStreamOpen = true,
|
||||
ArchiveEncoding = new ArchiveEncoding()
|
||||
{
|
||||
Default = Encoding.UTF8
|
||||
}
|
||||
});
|
||||
return ms;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 压缩多个文件
|
||||
/// </summary>
|
||||
/// <param name="files">多个文件路径,文件或文件夹</param>
|
||||
/// <param name="zipFile">压缩到...</param>
|
||||
/// <param name="rootdir">压缩包内部根文件夹</param>
|
||||
/// <param name="archiveType"></param>
|
||||
public static void Zip(List<string> files, string zipFile, string rootdir = "", ArchiveType archiveType = ArchiveType.SevenZip)
|
||||
{
|
||||
using var archive = CreateZipArchive(files, rootdir, archiveType);
|
||||
archive.SaveTo(zipFile, new WriterOptions(CompressionType.Deflate)
|
||||
{
|
||||
LeaveStreamOpen = true,
|
||||
ArchiveEncoding = new ArchiveEncoding()
|
||||
{
|
||||
Default = Encoding.UTF8
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解压文件,自动检测压缩包类型
|
||||
/// </summary>
|
||||
/// <param name="compressedFile">rar文件</param>
|
||||
/// <param name="dir">解压到...</param>
|
||||
/// <param name="ignoreEmptyDir">忽略空文件夹</param>
|
||||
public static void Decompress(string compressedFile, string dir = "", bool ignoreEmptyDir = true)
|
||||
{
|
||||
if (string.IsNullOrEmpty(dir))
|
||||
{
|
||||
dir = Path.GetDirectoryName(compressedFile);
|
||||
}
|
||||
|
||||
using Stream stream = File.OpenRead(compressedFile);
|
||||
using var reader = ReaderFactory.Open(stream);
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (ignoreEmptyDir)
|
||||
{
|
||||
reader.WriteEntryToDirectory(dir, new ExtractionOptions()
|
||||
{
|
||||
ExtractFullPath = true,
|
||||
Overwrite = true
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!reader.Entry.IsDirectory)
|
||||
{
|
||||
reader.WriteEntryToDirectory(dir, new ExtractionOptions()
|
||||
{
|
||||
ExtractFullPath = true,
|
||||
Overwrite = true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建zip包
|
||||
/// </summary>
|
||||
/// <param name="files"></param>
|
||||
/// <param name="rootdir"></param>
|
||||
/// <param name="archiveType"></param>
|
||||
/// <returns></returns>
|
||||
private static IWritableArchive CreateZipArchive(List<string> files, string rootdir, ArchiveType archiveType = ArchiveType.SevenZip)
|
||||
{
|
||||
var archive = ArchiveFactory.Create(archiveType);
|
||||
var dic = GetFileEntryMaps(files);
|
||||
var remoteUrls = files.Distinct().Where(s => s.StartsWith("http")).Select(s =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Uri(s);
|
||||
}
|
||||
catch (UriFormatException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}).Where(u => u != null).ToList();
|
||||
foreach (var pair in dic)
|
||||
{
|
||||
archive.AddEntry(Path.Combine(rootdir, pair.Value), pair.Key);
|
||||
}
|
||||
|
||||
if (!remoteUrls.Any())
|
||||
{
|
||||
return archive;
|
||||
}
|
||||
|
||||
var streams = new ConcurrentDictionary<string, Stream>();
|
||||
using var httpClient = new HttpClient();
|
||||
Parallel.ForEach(remoteUrls, url =>
|
||||
{
|
||||
httpClient.GetAsync(url).ContinueWith(async t =>
|
||||
{
|
||||
if (t.IsCompleted)
|
||||
{
|
||||
var res = await t;
|
||||
if (res.IsSuccessStatusCode)
|
||||
{
|
||||
Stream stream = await res.Content.ReadAsStreamAsync();
|
||||
streams[Path.Combine(rootdir, Path.GetFileName(HttpUtility.UrlDecode(url.AbsolutePath)))] = stream;
|
||||
}
|
||||
}
|
||||
}).Wait();
|
||||
});
|
||||
foreach (var kv in streams)
|
||||
{
|
||||
archive.AddEntry(kv.Key, kv.Value, true);
|
||||
}
|
||||
|
||||
return archive;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取文件路径和zip-entry的映射
|
||||
/// </summary>
|
||||
/// <param name="files"></param>
|
||||
/// <returns></returns>
|
||||
private static Dictionary<string, string> GetFileEntryMaps(List<string> files)
|
||||
{
|
||||
var fileList = new List<string>();
|
||||
void GetFilesRecurs(string path)
|
||||
{
|
||||
//遍历目标文件夹的所有文件
|
||||
fileList.AddRange(Directory.GetFiles(path));
|
||||
|
||||
//遍历目标文件夹的所有文件夹
|
||||
foreach (string directory in Directory.GetDirectories(path))
|
||||
{
|
||||
GetFilesRecurs(directory);
|
||||
}
|
||||
}
|
||||
|
||||
files.Where(s => !s.StartsWith("http")).ForEach(s =>
|
||||
{
|
||||
if (Directory.Exists(s))
|
||||
{
|
||||
GetFilesRecurs(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
fileList.Add(s);
|
||||
}
|
||||
});
|
||||
if (!fileList.Any())
|
||||
{
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
var dirname = new string(fileList.First().Substring(0, fileList.Min(s => s.Length)).TakeWhile((c, i) => fileList.All(s => s[i] == c)).ToArray());
|
||||
if (!Directory.Exists(dirname))
|
||||
{
|
||||
dirname = Directory.GetParent(dirname).FullName;
|
||||
}
|
||||
|
||||
var dic = fileList.ToDictionary(s => s, s => s.Substring(dirname.Length));
|
||||
return dic;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user