添加项目文件。

This commit is contained in:
DK
2022-03-28 15:27:40 +08:00
parent b620fcb0cf
commit dc78fd1a09
898 changed files with 173053 additions and 0 deletions
@@ -0,0 +1,61 @@
//using System;
//using System.Linq.Expressions;
//namespace IRaCIS.Core.Infrastructure.ExpressionExtend
//{
// /// <summary>
// /// 合并表达式 And Or Not扩展
// /// </summary>
// public static class ExpressionExtend
// {
// /// <summary>
// /// 合并表达式 expr1 AND expr2
// /// </summary>
// /// <typeparam name="T"></typeparam>
// /// <param name="expr1"></param>
// /// <param name="expr2"></param>
// /// <returns></returns>
// public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
// {
// if (expr1 == null) return expr2;
// else if (expr2 == null) return expr1;
// //return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, expr2.Body), expr1.Parameters);
// ParameterExpression newParameter = Expression.Parameter(typeof(T), "c");
// NewExpressionVisitor visitor = new NewExpressionVisitor(newParameter);
// var left = visitor.Replace(expr1.Body);
// var right = visitor.Replace(expr2.Body);
// var body = Expression.And(left, right);
// return Expression.Lambda<Func<T, bool>>(body, newParameter);
// }
// /// <summary>
// /// 合并表达式 expr1 or expr2
// /// </summary>
// /// <typeparam name="T"></typeparam>
// /// <param name="expr1"></param>
// /// <param name="expr2"></param>
// /// <returns></returns>
// public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
// {
// if (expr1 == null) return expr2;
// else if (expr2 == null) return expr1;
// ParameterExpression newParameter = Expression.Parameter(typeof(T), "c");
// NewExpressionVisitor visitor = new NewExpressionVisitor(newParameter);
// var left = visitor.Replace(expr1.Body);
// var right = visitor.Replace(expr2.Body);
// var body = Expression.Or(left, right);
// return Expression.Lambda<Func<T, bool>>(body, newParameter);
// }
// public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expr)
// {
// if (expr == null) return null;
// var candidateExpr = expr.Parameters[0];
// var body = Expression.Not(expr.Body);
// return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
// }
// }
//}
@@ -0,0 +1,447 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Infrastructure.Extention
{
public class Expressionable<T> where T : class, new()
{
Expression<Func<T, bool>> _exp = null;
public Expressionable<T> And(Expression<Func<T, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, bool>>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T> AndIF(bool isAnd, Expression<Func<T, bool>> exp)
{
if (isAnd)
And(exp);
return this;
}
public Expressionable<T> Or(Expression<Func<T, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, bool>>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T> OrIF(bool isOr, Expression<Func<T, bool>> exp)
{
if (isOr)
Or(exp);
return this;
}
public Expression<Func<T, bool>> ToExpression()
{
if (_exp == null)
_exp = it => true;
return _exp;
}
}
public class Expressionable<T, T2> where T : class, new() where T2 : class, new()
{
Expression<Func<T, T2, bool>> _exp = null;
public Expressionable<T, T2> And(Expression<Func<T, T2, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, bool>>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2> AndIF(bool isAnd, Expression<Func<T, T2, bool>> exp)
{
if (isAnd)
And(exp);
return this;
}
public Expressionable<T, T2> Or(Expression<Func<T, T2, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, bool>>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2> OrIF(bool isOr, Expression<Func<T, T2, bool>> exp)
{
if (isOr)
Or(exp);
return this;
}
public Expression<Func<T, T2, bool>> ToExpression()
{
if (_exp == null)
_exp = (it, t2) => true;
return _exp;
}
}
public class Expressionable<T, T2, T3> where T : class, new() where T2 : class, new() where T3 : class, new()
{
Expression<Func<T, T2, T3, bool>> _exp = null;
public Expressionable<T, T2, T3> And(Expression<Func<T, T2, T3, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, bool>>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3> AndIF(bool isAnd, Expression<Func<T, T2, T3, bool>> exp)
{
if (isAnd)
And(exp);
return this;
}
public Expressionable<T, T2, T3> Or(Expression<Func<T, T2, T3, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, bool>>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3> OrIF(bool isOr, Expression<Func<T, T2, T3, bool>> exp)
{
if (isOr)
Or(exp);
return this;
}
public Expression<Func<T, T2, T3, bool>> ToExpression()
{
if (_exp == null)
_exp = (it, t2, t3) => true;
return _exp;
}
}
public class Expressionable<T, T2, T3, T4> where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new()
{
Expression<Func<T, T2, T3, T4, bool>> _exp = null;
public Expressionable<T, T2, T3, T4> And(Expression<Func<T, T2, T3, T4, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, T4, bool>>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3, T4> AndIF(bool isAnd, Expression<Func<T, T2, T3, T4, bool>> exp)
{
if (isAnd)
And(exp);
return this;
}
public Expressionable<T, T2, T3, T4> Or(Expression<Func<T, T2, T3, T4, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, T4, bool>>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3, T4> OrIF(bool isOr, Expression<Func<T, T2, T3, T4, bool>> exp)
{
if (isOr)
Or(exp);
return this;
}
public Expression<Func<T, T2, T3, T4, bool>> ToExpression()
{
if (_exp == null)
_exp = (it, t2, t3, t4) => true;
return _exp;
}
}
public class Expressionable<T, T2, T3, T4, T5> where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new()
{
Expression<Func<T, T2, T3, T4, T5, bool>> _exp = null;
public Expressionable<T, T2, T3, T4, T5> And(Expression<Func<T, T2, T3, T4, T5, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, T4, T5, bool>>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3, T4, T5> AndIF(bool isAnd, Expression<Func<T, T2, T3, T4, T5, bool>> exp)
{
if (isAnd)
And(exp);
return this;
}
public Expressionable<T, T2, T3, T4, T5> Or(Expression<Func<T, T2, T3, T4, T5, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, T4, T5, bool>>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3, T4, T5> OrIF(bool isOr, Expression<Func<T, T2, T3, T4, T5, bool>> exp)
{
if (isOr)
Or(exp);
return this;
}
public Expression<Func<T, T2, T3, T4, T5, bool>> ToExpression()
{
if (_exp == null)
_exp = (it, t2, t3, t4, T5) => true;
return _exp;
}
}
public class Expressionable<T, T2, T3, T4, T5, T6> where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new() where T6 : class, new()
{
Expression<Func<T, T2, T3, T4, T5, T6, bool>> _exp = null;
public Expressionable<T, T2, T3, T4, T5, T6> And(Expression<Func<T, T2, T3, T4, T5, T6, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, T4, T5, T6, bool>>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3, T4, T5, T6> AndIF(bool isAnd, Expression<Func<T, T2, T3, T4, T5, T6, bool>> exp)
{
if (isAnd)
And(exp);
return this;
}
public Expressionable<T, T2, T3, T4, T5, T6> Or(Expression<Func<T, T2, T3, T4, T5, T6, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, T4, T5, T6, bool>>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3, T4, T5, T6> OrIF(bool isOr, Expression<Func<T, T2, T3, T4, T5, T6, bool>> exp)
{
if (isOr)
Or(exp);
return this;
}
public Expression<Func<T, T2, T3, T4, T5, T6, bool>> ToExpression()
{
if (_exp == null)
_exp = (it, t2, t3, t4, T5, t6) => true;
return _exp;
}
}
public class Expressionable<T, T2, T3, T4, T5, T6, T7> where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new() where T6 : class, new() where T7 : class, new()
{
Expression<Func<T, T2, T3, T4, T5, T6, T7, bool>> _exp = null;
public Expressionable<T, T2, T3, T4, T5, T6, T7> And(Expression<Func<T, T2, T3, T4, T5, T6, T7, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, T4, T5, T6, T7, bool>>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3, T4, T5, T6, T7> AndIF(bool isAnd, Expression<Func<T, T2, T3, T4, T5, T6, T7, bool>> exp)
{
if (isAnd)
And(exp);
return this;
}
public Expressionable<T, T2, T3, T4, T5, T6, T7> Or(Expression<Func<T, T2, T3, T4, T5, T6, T7, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, T4, T5, T6, T7, bool>>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3, T4, T5, T6, T7> OrIF(bool isOr, Expression<Func<T, T2, T3, T4, T5, T6, T7, bool>> exp)
{
if (isOr)
Or(exp);
return this;
}
public Expression<Func<T, T2, T3, T4, T5, T6, T7, bool>> ToExpression()
{
if (_exp == null)
_exp = (it, t2, t3, t4, T5, t6, t7) => true;
return _exp;
}
}
public class Expressionable<T, T2, T3, T4, T5, T6, T7, T8> where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new() where T6 : class, new() where T7 : class, new() where T8 : class, new()
{
Expression<Func<T, T2, T3, T4, T5, T6, T7, T8, bool>> _exp = null;
public Expressionable<T, T2, T3, T4, T5, T6, T7, T8> And(Expression<Func<T, T2, T3, T4, T5, T6, T7, T8, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, T4, T5, T6, T7, T8, bool>>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3, T4, T5, T6, T7, T8> AndIF(bool isAnd, Expression<Func<T, T2, T3, T4, T5, T6, T7, T8, bool>> exp)
{
if (isAnd)
And(exp);
return this;
}
public Expressionable<T, T2, T3, T4, T5, T6, T7, T8> Or(Expression<Func<T, T2, T3, T4, T5, T6, T7, T8, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, T4, T5, T6, T7, T8, bool>>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3, T4, T5, T6, T7, T8> OrIF(bool isOr, Expression<Func<T, T2, T3, T4, T5, T6, T7, T8, bool>> exp)
{
if (isOr)
Or(exp);
return this;
}
public Expression<Func<T, T2, T3, T4, T5, T6, T7, T8, bool>> ToExpression()
{
if (_exp == null)
_exp = (it, t2, t3, t4, T5, t6, t7, t8) => true;
return _exp;
}
}
public class Expressionable<T, T2, T3, T4, T5, T6, T7, T8, T9> where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new() where T6 : class, new() where T7 : class, new() where T8 : class, new() where T9 : class, new()
{
Expression<Func<T, T2, T3, T4, T5, T6, T7, T8, T9, bool>> _exp = null;
public Expressionable<T, T2, T3, T4, T5, T6, T7, T8, T9> And(Expression<Func<T, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, T4, T5, T6, T7, T8, T9, bool>>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3, T4, T5, T6, T7, T8, T9> AndIF(bool isAnd, Expression<Func<T, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp)
{
if (isAnd)
And(exp);
return this;
}
public Expressionable<T, T2, T3, T4, T5, T6, T7, T8, T9> Or(Expression<Func<T, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp)
{
if (_exp == null)
_exp = exp;
else
_exp = Expression.Lambda<Func<T, T2, T3, T4, T5, T6, T7, T8, T9, bool>>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters);
return this;
}
public Expressionable<T, T2, T3, T4, T5, T6, T7, T8, T9> OrIF(bool isOr, Expression<Func<T, T2, T3, T4, T5, T6, T7, T8, T9, bool>> exp)
{
if (isOr)
Or(exp);
return this;
}
public Expression<Func<T, T2, T3, T4, T5, T6, T7, T8, T9, bool>> ToExpression()
{
if (_exp == null)
_exp = (it, t2, t3, t4, T5, t6, t7, t8, t9) => true;
return _exp;
}
}
public class Expressionable
{
public static Expressionable<T> Create<T>() where T : class, new()
{
return new Expressionable<T>();
}
public static Expressionable<T, T2> Create<T, T2>() where T : class, new() where T2 : class, new()
{
return new Expressionable<T, T2>();
}
public static Expressionable<T, T2, T3> Create<T, T2, T3>() where T : class, new() where T2 : class, new() where T3 : class, new()
{
return new Expressionable<T, T2, T3>();
}
public static Expressionable<T, T2, T3, T4> Create<T, T2, T3, T4>() where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new()
{
return new Expressionable<T, T2, T3, T4>();
}
public static Expressionable<T, T2, T3, T4, T5> Create<T, T2, T3, T4, T5>() where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new()
{
return new Expressionable<T, T2, T3, T4, T5>();
}
public static Expressionable<T, T2, T3, T4, T5, T6> Create<T, T2, T3, T4, T5, T6>() where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new() where T6 : class, new()
{
return new Expressionable<T, T2, T3, T4, T5, T6>();
}
public static Expressionable<T, T2, T3, T4, T5, T6, T7> Create<T, T2, T3, T4, T5, T6, T7>() where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new() where T6 : class, new() where T7 : class, new()
{
return new Expressionable<T, T2, T3, T4, T5, T6, T7>();
}
public static Expressionable<T, T2, T3, T4, T5, T6, T7, T8> Create<T, T2, T3, T4, T5, T6, T7, T8>() where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new() where T6 : class, new() where T7 : class, new() where T8 : class, new()
{
return new Expressionable<T, T2, T3, T4, T5, T6, T7, T8>();
}
public static Expressionable<T, T2, T3, T4, T5, T6, T7, T8, T9> Create<T, T2, T3, T4, T5, T6, T7, T8, T9>() where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new() where T6 : class, new() where T7 : class, new() where T8 : class, new() where T9 : class, new()
{
return new Expressionable<T, T2, T3, T4, T5, T6, T7, T8, T9>();
}
}
}
@@ -0,0 +1,24 @@
using System.Linq.Expressions;
namespace IRaCIS.Core.Infrastructure.ExpressionExtend
{
/// <summary>
/// 建立新表达式
/// </summary>
internal class NewExpressionVisitor : ExpressionVisitor
{
public ParameterExpression _NewParameter { get; private set; }
public NewExpressionVisitor(ParameterExpression param)
{
this._NewParameter = param;
}
public Expression Replace(Expression exp)
{
return this.Visit(exp);
}
protected override Expression VisitParameter(ParameterExpression node)
{
return this._NewParameter;
}
}
}
@@ -0,0 +1,66 @@
using IRaCIS.Core.Infrastructure.ExpressionExtend;
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace IRaCIS.Core.Infrastructure.ExpressionExtend
{
public static class QueryableExtension
{
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> query, string propertyName)
{
Type type = typeof(T);
PropertyInfo property = type.GetProperty(propertyName);
if (property == null)
throw new ArgumentException(propertyName, "Not Exist");
return OrderBy(query, propertyName, false);
}
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> query, string propertyName)
{
Type type = typeof(T);
PropertyInfo property = type.GetProperty(propertyName);
if (property == null)
throw new ArgumentException(propertyName, "Not Exist");
return OrderBy(query, propertyName, true);
}
static IOrderedQueryable<T> OrderBy<T>(IQueryable<T> query, string propertyName, bool isDesc)
{
string methodName = isDesc ? "OrderByDescendingInternal" : "OrderByInternal";
var memberProp = typeof(T).GetProperty(propertyName);
var method = typeof(QueryableExtension).GetMethod(methodName)
.MakeGenericMethod(typeof(T), memberProp.PropertyType);
return (IOrderedQueryable<T>)method.Invoke(null, new object[] { query, memberProp });
}
public static IOrderedQueryable<T> OrderByInternal<T, TProp>(IQueryable<T> query, PropertyInfo memberProperty)
{
return query.OrderBy(_GetLamba<T, TProp>(memberProperty));
}
public static IOrderedQueryable<T> OrderByDescendingInternal<T, TProp>(IQueryable<T> query, PropertyInfo memberProperty)
{
return query.OrderByDescending(_GetLamba<T, TProp>(memberProperty));
}
static Expression<Func<T, TProp>> _GetLamba<T, TProp>(PropertyInfo memberProperty)
{
if (memberProperty.PropertyType != typeof(TProp)) throw new Exception();
var thisArg = Expression.Parameter(typeof(T));
var lamba = Expression.Lambda<Func<T, TProp>>(Expression.Property(thisArg, memberProperty), thisArg);
return lamba;
}
}
}
@@ -0,0 +1,18 @@
namespace IRaCIS.Core.Infra.Common.Cache
{
/// <summary>
/// 缓存类型
/// </summary>
public enum CacheType
{
/// <summary>
/// 内存缓存
/// </summary>
Memory,
/// <summary>
/// Redis缓存
/// </summary>
Redis
}
}
+107
View File
@@ -0,0 +1,107 @@
using System;
using System.Threading.Tasks;
namespace IRaCIS.Core.Infra.Common.Cache
{
/// <summary>
/// 缓存接口
/// </summary>
public interface ICache
{
/// <summary>
/// 用于在 key 存在时删除 key
/// </summary>
/// <param name="key">键</param>
long Del(params string[] key);
/// <summary>
/// 用于在 key 存在时删除 key
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
Task<long> DelAsync(params string[] key);
/// <summary>
/// 用于在 key 模板存在时删除
/// </summary>
/// <param name="pattern">key模板</param>
/// <returns></returns>
Task<long> DelByPatternAsync(string pattern);
/// <summary>
/// 检查给定 key 是否存在
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
bool Exists(string key);
/// <summary>
/// 检查给定 key 是否存在
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
Task<bool> ExistsAsync(string key);
/// <summary>
/// 获取指定 key 的值
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
string Get(string key);
/// <summary>
/// 获取指定 key 的值
/// </summary>
/// <typeparam name="T">byte[] 或其他类型</typeparam>
/// <param name="key">键</param>
/// <returns></returns>
T Get<T>(string key);
/// <summary>
/// 获取指定 key 的值
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
Task<string> GetAsync(string key);
/// <summary>
/// 获取指定 key 的值
/// </summary>
/// <typeparam name="T">byte[] 或其他类型</typeparam>
/// <param name="key">键</param>
/// <returns></returns>
Task<T> GetAsync<T>(string key);
/// <summary>
/// 设置指定 key 的值,所有写入参数object都支持string | byte[] | 数值 | 对象
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
bool Set(string key, object value);
/// <summary>
/// 设置指定 key 的值,所有写入参数object都支持string | byte[] | 数值 | 对象
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="expire">有效期</param>
bool Set(string key, object value, TimeSpan expire);
/// <summary>
/// 设置指定 key 的值,所有写入参数object都支持string | byte[] | 数值 | 对象
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <returns></returns>
Task<bool> SetAsync(string key, object value);
/// <summary>
/// 设置指定 key 的值,所有写入参数object都支持string | byte[] | 数值 | 对象
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="expire">有效期</param>
/// <returns></returns>
Task<bool> SetAsync(string key, object value, TimeSpan expire);
}
}
@@ -0,0 +1,127 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
namespace IRaCIS.Core.Infra.Common.Cache
{
/// <summary>
/// 内存缓存
/// </summary>
public class MemoryCache : ICache
{
private readonly IMemoryCache _memoryCache;
public MemoryCache(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}
public long Del(params string[] key)
{
foreach(var k in key)
{
_memoryCache.Remove(k);
}
return key.Length;
}
public Task<long> DelAsync(params string[] key)
{
foreach (var k in key)
{
_memoryCache.Remove(k);
}
return Task.FromResult((long)key.Length);
}
public async Task<long> DelByPatternAsync(string pattern)
{
if (string.IsNullOrEmpty(pattern))
return default;
pattern = Regex.Replace(pattern, @"\{.*\}", "(.*)");
var keys = GetAllKeys().Where(k => Regex.IsMatch(k, pattern));
if(keys != null && keys.Count() > 0)
{
return await DelAsync(keys.ToArray());
}
return default;
}
public bool Exists(string key)
{
return _memoryCache.TryGetValue(key, out _);
}
public Task<bool> ExistsAsync(string key)
{
return Task.FromResult(_memoryCache.TryGetValue(key, out _));
}
public string Get(string key)
{
return _memoryCache.Get(key)?.ToString();
}
public T Get<T>(string key)
{
return _memoryCache.Get<T>(key);
}
public Task<string> GetAsync(string key)
{
return Task.FromResult(Get(key));
}
public Task<T> GetAsync<T>(string key)
{
return Task.FromResult(Get<T>(key));
}
public bool Set(string key, object value)
{
_memoryCache.Set(key, value);
return true;
}
public bool Set(string key, object value, TimeSpan expire)
{
_memoryCache.Set(key, value, expire);
return true;
}
public Task<bool> SetAsync(string key, object value)
{
Set(key, value);
return Task.FromResult(true);
}
public Task<bool> SetAsync(string key, object value, TimeSpan expire)
{
Set(key, value, expire);
return Task.FromResult(true);
}
private List<string> GetAllKeys()
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
var entries = _memoryCache.GetType().GetField("_entries", flags).GetValue(_memoryCache);
var cacheItems = entries as IDictionary;
var keys = new List<string>();
if (cacheItems == null) return keys;
foreach (DictionaryEntry cacheItem in cacheItems)
{
keys.Add(cacheItem.Key.ToString());
}
return keys;
}
}
}
@@ -0,0 +1,88 @@
using System;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace IRaCIS.Core.Infra.Common.Cache
{
/// <summary>
/// Redis缓存
/// </summary>
public class RedisCache : ICache
{
public long Del(params string[] key)
{
return RedisHelper.Del(key);
}
public Task<long> DelAsync(params string[] key)
{
return RedisHelper.DelAsync(key);
}
public async Task<long> DelByPatternAsync(string pattern)
{
if (string.IsNullOrEmpty(pattern))
return default;
pattern = Regex.Replace(pattern, @"\{.*\}", "*");
var keys = (await RedisHelper.KeysAsync(pattern));
if(keys != null && keys.Length > 0)
{
return await RedisHelper.DelAsync(keys);
}
return default;
}
public bool Exists(string key)
{
return RedisHelper.Exists(key);
}
public Task<bool> ExistsAsync(string key)
{
return RedisHelper.ExistsAsync(key);
}
public string Get(string key)
{
return RedisHelper.Get(key);
}
public T Get<T>(string key)
{
return RedisHelper.Get<T>(key);
}
public Task<string> GetAsync(string key)
{
return RedisHelper.GetAsync(key);
}
public Task<T> GetAsync<T>(string key)
{
return RedisHelper.GetAsync<T>(key);
}
public bool Set(string key, object value)
{
return RedisHelper.Set(key, value);
}
public bool Set(string key, object value, TimeSpan expire)
{
return RedisHelper.Set(key, value, expire);
}
public Task<bool> SetAsync(string key, object value)
{
return RedisHelper.SetAsync(key, value);
}
public Task<bool> SetAsync(string key, object value, TimeSpan expire)
{
return RedisHelper.SetAsync(key, value, expire);
}
}
}
@@ -0,0 +1,17 @@
using System;
namespace IRaCIS.Core.Infrastructure
{
public class BusinessValidationFailedException : Exception
{
public BusinessValidationFailedException()
{
}
public BusinessValidationFailedException( string message) : base(message)
{
}
}
}
@@ -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;
}
}
}
@@ -0,0 +1,43 @@
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Http;
namespace IRaCIS.Core.Infrastructure
{
public class IPHelper
{
/// <summary>
/// 是否为ip
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
public static bool IsIP(string ip)
{
return Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
}
public static string GetIP(HttpRequest request)
{
if (request == null)
{
return "";
}
string ip = request.Headers["X-Real-IP"].FirstOrDefault();
if (string.IsNullOrEmpty(ip))
{
ip = request.Headers["X-Forwarded-For"].FirstOrDefault();
}
if (string.IsNullOrEmpty(ip))
{
ip = request.HttpContext?.Connection?.RemoteIpAddress?.ToString();
}
if (string.IsNullOrEmpty(ip) || !IsIP(ip))
{
ip = "127.0.0.1";
}
return ip;
}
}
}
@@ -0,0 +1,20 @@
using System.Security.Cryptography;
using System.Text;
namespace IRaCIS.Core.Infrastructure
{
public class MD5Helper
{
public static string Md5(string target)
{
using (MD5 md5 = MD5.Create())
{ // MD5非线程安全
byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(target));
StringBuilder sb = new StringBuilder(32);
for (int i = 0; i < bytes.Length; ++i)
sb.Append(bytes[i].ToString("x2"));
return sb.ToString();
}
}
}
}
@@ -0,0 +1,52 @@
using System;
using System.IO;
using ICSharpCode.SharpZipLib.Checksum;
using ICSharpCode.SharpZipLib.Zip;
namespace IRaCIS.Core.Infrastructure
{
public class ZipHelper
{
public static void CreateZip(string sourceFilePath, string destinationZipFilePath)
{
if (sourceFilePath[sourceFilePath.Length - 1] != Path.DirectorySeparatorChar)
sourceFilePath += Path.DirectorySeparatorChar;
ZipOutputStream zipStream = new ZipOutputStream(File.Create(destinationZipFilePath));
zipStream.SetLevel(6); // 压缩级别 0-9
CreateZipFiles(sourceFilePath, zipStream);
zipStream.Finish();
zipStream.Close();
}
private static void CreateZipFiles(string sourceFilePath, ZipOutputStream zipStream)
{
Crc32 crc = new Crc32();
string[] filesArray = Directory.GetFileSystemEntries(sourceFilePath);
foreach (string file in filesArray)
{
if (Directory.Exists(file)) //如果当前是文件夹,递归
{
CreateZipFiles(file, zipStream);
}
else //如果是文件,开始压缩
{
FileStream fileStream = File.OpenRead(file);
byte[] buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, buffer.Length);
string tempFile = file.Substring(sourceFilePath.LastIndexOf("\\") + 1);
ZipEntry entry = new ZipEntry(tempFile);
entry.DateTime = DateTime.Now;
entry.Size = fileStream.Length;
fileStream.Close();
crc.Reset();
crc.Update(buffer);
entry.Crc = crc.Value;
zipStream.PutNextEntry(entry);
zipStream.Write(buffer, 0, buffer.Length);
}
}
}
}
}
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>..\bin</OutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="10.1.1" />
<PackageReference Include="CSRedisCore" Version="3.6.6" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
<PackageReference Include="SharpCompress" Version="0.30.1" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.14" />
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
</Project>