添加公用类

This commit is contained in:
cli 2024-10-22 09:28:58 +08:00
parent 5d07a846c8
commit 1a7be7a6af
37 changed files with 3727 additions and 17 deletions

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace JiShe.CollectBus.Common.Consts
{
public class RegexConst
{
public const string PhoneNumber = "1[3|4|5|7|8|9][0-9]{9}";
public const string IsNumeric = @"^[+-]?\d+[.]?\d*$";
public const string Ip = @"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$";
public const string Email = @"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$";
public const string Url = @"^(ht|f)tp(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&%\$#_]*)?$";
public const string Date = @"(\d{4})-(\d{1,2})-(\d{1,2})";
public const string ZipCode = @"^\d{6}$";
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace JiShe.CollectBus.Common.Enums
{
public enum MaskTypeEnum
{
/// <summary>
/// Masks all characters within the masking region, regardless of type.
/// </summary>
All,
/// <summary>
/// Masks only alphabetic and numeric characters within the masking region.
/// </summary>
AlphaNumericOnly,
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace JiShe.CollectBus.Common.Enums
{
public enum SortEnum
{
Asc,
Desc
}
}

View File

@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using JetBrains.Annotations;
namespace JiShe.CollectBus.Common.Extensions
{
/// <summary>
/// Extension methods for Collections.
/// </summary>
public static class CollectionExtensions
{
/// <summary>
/// Checks whatever given collection object is null or has no item.
/// </summary>
[Description("检查给定的集合对象是否为null或没有项目")]
public static bool IsNullOrEmpty<T>([CanBeNull] this ICollection<T> source)
{
return source == null || source.Count <= 0;
}
/// <summary>
/// Adds an item to the collection if it's not already in the collection.
/// </summary>
/// <param name="source">Collection</param>
/// <param name="item">Item to check and add</param>
/// <typeparam name="T">Type of the items in the collection</typeparam>
/// <returns>Returns True if added, returns False if not.</returns>
[Description("项不在集合中则将其添加到集合中")]
public static bool AddIfNotContains<T>([NotNull] this ICollection<T> source, T item)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (source.Contains(item))
{
return false;
}
source.Add(item);
return true;
}
/// <summary>
/// Adds items to the collection which are not already in the collection.
/// </summary>
/// <param name="source">The collection</param>
/// <param name="items">Item to check and add</param>
/// <typeparam name="T">Type of the items in the collection</typeparam>
/// <returns>Returns the added items.</returns>
public static IEnumerable<T> AddIfNotContains<T>([NotNull] this ICollection<T> source, IEnumerable<T> items)
{
var addedItems = new List<T>();
foreach (var item in items)
{
if (source.Contains(item))
{
continue;
}
source.Add(item);
addedItems.Add(item);
}
return addedItems;
}
/// <summary>
/// Adds an item to the collection if it's not already in the collection based on the given <paramref name="predicate"/>.
/// </summary>
/// <param name="source">The collection</param>
/// <param name="predicate">The condition to decide if the item is already in the collection</param>
/// <param name="itemFactory">A factory that returns the item</param>
/// <typeparam name="T">Type of the items in the collection</typeparam>
/// <returns>Returns True if added, returns False if not.</returns>
public static bool AddIfNotContains<T>([NotNull] this ICollection<T> source, [NotNull] Func<T, bool> predicate, [NotNull] Func<T> itemFactory)
{
if (source.Any(predicate))
{
return false;
}
source.Add(itemFactory());
return true;
}
/// <summary>
/// Removes all items from the collection those satisfy the given <paramref name="predicate"/>.
/// </summary>
/// <typeparam name="T">Type of the items in the collection</typeparam>
/// <param name="source">The collection</param>
/// <param name="predicate">The condition to remove the items</param>
/// <returns>List of removed items</returns>
[Description("从集合中移除满足给定条件的所有项")]
public static IList<T> RemoveAll<T>([NotNull] this ICollection<T> source, Func<T, bool> predicate)
{
var items = source.Where(predicate).ToList();
foreach (var item in items)
{
source.Remove(item);
}
return items;
}
/// <summary>
/// Removes all items from the collection those satisfy the given <paramref name="predicate"/>.
/// </summary>
/// <typeparam name="T">Type of the items in the collection</typeparam>
/// <param name="source">The collection</param>
/// <param name="items">Items to be removed from the list</param>
public static void RemoveAll<T>([NotNull] this ICollection<T> source, IEnumerable<T> items)
{
foreach (var item in items)
{
source.Remove(item);
}
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.ComponentModel;
namespace JiShe.CollectBus.Common.Extensions
{
/// <summary>
/// Extension methods for <see cref="IComparable{T}"/>.
/// </summary>
public static class ComparableExtensions
{
/// <summary>
/// Checks a value is between a minimum and maximum value.
/// </summary>
/// <param name="value">The value to be checked</param>
/// <param name="minInclusiveValue">Minimum (inclusive) value</param>
/// <param name="maxInclusiveValue">Maximum (inclusive) value</param>
[Description("检查值是否介于最小值和最大值之间")]
public static bool IsBetween<T>(this T value, T minInclusiveValue, T maxInclusiveValue) where T : IComparable<T>
{
return value.CompareTo(minInclusiveValue) >= 0 && value.CompareTo(maxInclusiveValue) <= 0;
}
}
}

View File

@ -0,0 +1,291 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Xml.Linq;
namespace JiShe.CollectBus.Common.Extensions
{
public static class DataTableExtensions
{
/// <summary>Converts to list.</summary>
/// <typeparam name="T"></typeparam>
/// <param name="dt">The dt.</param>
/// <returns>
/// <br />
/// </returns>
[Description("转换为列表")]
public static IList<T> ToList<T>(this DataTable dt) where T : class
{
IList<T> list = new List<T>();
foreach (DataRow dr in dt.Rows)
{
T t = Activator.CreateInstance<T>();
var props = typeof(T).GetProperties();
foreach (var pro in props)
{
var tempName = pro.Name;
if (!dt.Columns.Contains(tempName)) continue;
if (!pro.CanWrite) continue;
var value = dr[tempName];
if (value != DBNull.Value)
pro.SetValue(t, value, null);
}
list.Add(t);
}
return list;
}
/// <summary>Converts to data table.</summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <returns>
/// <br />
/// </returns>
[Description("转换为DataTable")]
public static DataTable ToDataTable<T>(this ICollection<T> source)
{
var props = typeof(T).GetProperties();
var dt = new DataTable();
dt.Columns.AddRange(props.Select(p =>
new DataColumn(p.Name,
(p.PropertyType.IsGenericType) && (p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
? p.PropertyType.GetGenericArguments()[0]
: p.PropertyType)).ToArray());
for (var i = 0; i < source.Count; i++)
{
var tempList = new ArrayList();
foreach (var obj in props.Select(pi => pi.GetValue(source.ElementAt(i), null))) tempList.Add(obj);
var array = tempList.ToArray();
dt.LoadDataRow(array, true);
}
return dt;
}
/// <summary>Converts to xml.</summary>
/// <param name="dt">The dt.</param>
/// <param name="rootName">Name of the root.</param>
/// <returns>
/// <br />
/// </returns>
[Description("转换为Xml")]
public static XDocument ToXml(this DataTable dt, string rootName)
{
var xdoc = new XDocument
{
Declaration = new XDeclaration("1.0", "utf-8", "")
};
xdoc.Add(new XElement(rootName));
foreach (DataRow row in dt.Rows)
{
var element = new XElement(dt.TableName);
foreach (DataColumn col in dt.Columns)
{
element.Add(new XElement(col.ColumnName, row[col].ToString().Trim(' ')));
}
xdoc.Root?.Add(element);
}
return xdoc;
}
/// <summary>
/// "SELECT DISTINCT" over a DataTable
/// </summary>
/// <param name="sourceTable">Input DataTable</param>
/// <param name="fieldName">Field to select (distinct)</param>
/// <returns></returns>
[Description("在DataTable中'SELECT DISTINCT'")]
public static DataTable SelectDistinct(this DataTable sourceTable, string fieldName)
{
return SelectDistinct(sourceTable, fieldName, string.Empty);
}
/// <summary>
/// "SELECT DISTINCT" over a DataTable
/// </summary>
/// <param name="sourceTable">Input DataTable</param>
/// <param name="fieldNames">Fields to select (distinct) Split ','</param>
/// <param name="filter">Optional filter to be applied to the selection</param>
/// <returns></returns>
public static DataTable SelectDistinct(this DataTable sourceTable, string fieldNames, string filter)
{
var dt = new DataTable();
var arrFieldNames = fieldNames.Replace(" ", "").Split(',');
foreach (var s in arrFieldNames)
{
if (sourceTable.Columns.Contains(s))
dt.Columns.Add(s, sourceTable.Columns[s].DataType);
else
throw new Exception($"The column {s} does not exist.");
}
object[] lastValues = null;
foreach (DataRow dr in sourceTable.Select(filter, fieldNames))
{
var newValues = GetRowFields(dr, arrFieldNames);
if (lastValues == null || !(ObjectComparison(lastValues, newValues)))
{
lastValues = newValues;
dt.Rows.Add(lastValues);
}
}
return dt;
}
/// <summary>Selects the rows.</summary>
/// <param name="dt">The dt.</param>
/// <param name="whereExpression">The where expression.</param>
/// <param name="orderByExpression">The order by expression.</param>
/// <returns>
/// <br />
/// </returns>
[Description("查询全部行")]
public static DataTable SelectRows(this DataTable dt, string whereExpression, string orderByExpression)
{
dt.DefaultView.RowFilter = whereExpression;
dt.DefaultView.Sort = orderByExpression;
return dt.DefaultView.ToTable();
}
/// <summary>take any DataTable and remove duplicate rows based on any column.</summary>
/// <param name="dt">The dt.</param>
/// <param name="keyColName">Name of the key col.</param>
/// <returns>
/// <br />
/// </returns>
[Description("删除重复的行")]
public static DataTable Duplicate(this DataTable dt, string keyColName)
{
var tblOut = dt.Clone();
foreach (DataRow row in dt.Rows)
{
var found = false;
var caseIdToTest = row[keyColName].ToString();
foreach (DataRow row2 in tblOut.Rows)
{
if (row2[keyColName].ToString() == caseIdToTest)
{
found = true;
break;
}
}
if (!found)
tblOut.ImportRow(row);
}
return tblOut;
}
/// <summary>Checks if two DataTable objects have the same content.</summary>
/// <param name="thisDataTable">The this data table.</param>
/// <param name="otherDataTable">The other data table.</param>
/// <returns>
/// <br />
/// </returns>
[Description("检查两个DataTable对象是否具有相同的内容")]
public static bool EqualsByContent(this DataTable thisDataTable, DataTable otherDataTable)
{
// Compare row count.
if (thisDataTable.Rows.Count != otherDataTable.Rows.Count)
{
return false;
}
// Compare column count.
if (thisDataTable.Columns.Count != otherDataTable.Columns.Count)
{
return false;
}
// Compare data in each cell of each row.
for (int i = 0; i < thisDataTable.Rows.Count; i++)
{
for (int j = 0; j < thisDataTable.Columns.Count; j++)
{
if (!thisDataTable.Rows[i][j].Equals(otherDataTable.Rows[i][j]))
{
return false;
}
}
}
// The two DataTables contain the same data.
return true;
}
/// <summary>Renames the column.</summary>
/// <param name="dt">The dt.</param>
/// <param name="oldName">The old name.</param>
/// <param name="newName">The new name.</param>
[Description("重命名列")]
public static void RenameColumn(this DataTable dt, string oldName, string newName)
{
if (dt != null && !string.IsNullOrEmpty(oldName) && !string.IsNullOrEmpty(newName) && oldName != newName)
{
int idx = dt.Columns.IndexOf(oldName);
dt.Columns[idx].ColumnName = newName;
dt.AcceptChanges();
}
}
/// <summary>Removes the column.</summary>
/// <param name="dt">The dt.</param>
/// <param name="columnName">Name of the column.</param>
[Description("删除列")]
public static void RemoveColumn(this DataTable dt, string columnName)
{
if (dt != null && !string.IsNullOrEmpty(columnName) && dt.Columns.IndexOf(columnName) >= 0)
{
int idx = dt.Columns.IndexOf(columnName);
dt.Columns.RemoveAt(idx);
dt.AcceptChanges();
}
}
private static object[] GetRowFields(DataRow dr, string[] arrFieldNames)
{
if (arrFieldNames.Length == 1)
return new object[] { dr[arrFieldNames[0]] };
var itemArray = new ArrayList();
foreach (var field in arrFieldNames)
itemArray.Add(dr[field]);
return itemArray.ToArray();
}
private static bool ObjectComparison(object a, object b)
{
if (a == DBNull.Value && b == DBNull.Value) // both are DBNull.Value
return true;
if (a == DBNull.Value || b == DBNull.Value) // only one is DBNull.Value
return false;
return a.Equals(b); // value type standard comparison
}
private static bool ObjectComparison(IReadOnlyList<object> a, IReadOnlyList<object> b)
{
var retValue = true;
if (a.Count == b.Count)
for (var i = 0; i < a.Count; i++)
{
if (!ObjectComparison(a[i], b[i]))
{
retValue = false;
break;
}
retValue = true;
}
return retValue;
}
}
}

View File

@ -0,0 +1,171 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
namespace JiShe.CollectBus.Common.Extensions
{
public static class DateTimeExtensions
{
/// <summary>
/// Converts a DateTime to a Unix Timestamp
/// </summary>
/// <param name="target">This DateTime</param>
/// <returns></returns>
[Description("将日期时间转换为Unix时间戳")]
public static double ToUnixTimestamp(this DateTime target)
{
var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
var diff = target - origin;
return Math.Floor(diff.TotalSeconds);
}
/// <summary>
/// Converts a Unix Timestamp in to a DateTime
/// </summary>
/// <param name="unixTime">This Unix Timestamp</param>
/// <returns></returns>
[Description("将Unix时间戳转换为日期时间")]
public static DateTime FromUnixTimestamp(this double unixTime)
{
var epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0);
return epoch.AddSeconds(unixTime);
}
/// <summary>
/// Gets the value of the End of the day (23:59)
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
[Description("获取一天结束的值23:59")]
public static DateTime ToDayEnd(this DateTime target)
{
return target.Date.AddDays(1).AddMilliseconds(-1);
}
/// <summary>
/// Gets the First Date of the week for the specified date
/// </summary>
/// <param name="dt">this DateTime</param>
/// <param name="startOfWeek">The Start Day of the Week (ie, Sunday/Monday)</param>
/// <returns>The First Date of the week</returns>
[Description("获取指定日期的星期的第一个日期")]
public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
{
var diff = dt.DayOfWeek - startOfWeek;
if (diff < 0)
diff += 7;
return dt.AddDays(-1 * diff).Date;
}
/// <summary>
/// Returns all the days of a month.
/// </summary>
/// <param name="year">The year.</param>
/// <param name="month">The month.</param>
/// <returns></returns>
[Description("获取一个月的所有日期")]
public static IEnumerable<DateTime> DaysOfMonth(int year, int month)
{
return Enumerable.Range(0, DateTime.DaysInMonth(year, month))
.Select(day => new DateTime(year, month, day + 1));
}
/// <summary>
/// Determines the Nth instance of a Date's DayOfWeek in a month
/// </summary>
/// <returns></returns>
/// <example>11/29/2011 would return 5, because it is the 5th Tuesday of each month</example>
[Description("获取当前日期在一个月的第几个星期")]
public static int WeekDayInstanceOfMonth(this DateTime dateTime)
{
var y = 0;
return DaysOfMonth(dateTime.Year, dateTime.Month)
.Where(date => dateTime.DayOfWeek.Equals(date.DayOfWeek))
.Select(x => new { n = ++y, date = x })
.Where(x => x.date.Equals(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day)))
.Select(x => x.n).FirstOrDefault();
}
/// <summary>
/// Gets the total days in a month
/// </summary>
/// <param name="dateTime">The date time.</param>
/// <returns></returns>
[Description("获取一个月内的总天数")]
public static int TotalDaysInMonth(this DateTime dateTime)
{
return DaysOfMonth(dateTime.Year, dateTime.Month).Count();
}
/// <summary>
/// Get the first day in a month
/// </summary>
/// <param name="dateTime">The date time.</param>
/// <returns></returns>
[Description("获取一个月内的第一天")]
public static DateTime FirstInMonth(this DateTime dateTime)
{
return DateTime.Now.AddDays(1 - DateTime.Now.Day);
}
/// <summary>
/// Get the Last Day in a Month 23:59:59
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
[Description("获取一个月内的最后一天 23:59:59")]
public static DateTime LastInMonth(this DateTime dateTime)
{
return DateTime.Now.AddDays(1 - DateTime.Now.Day).Date.AddMonths(1).AddSeconds(-1);
}
/// <summary>
/// Takes any date and returns it's value as an Unspecified DateTime
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
[Description("获取Unspecified日期")]
public static DateTime ToDateTimeUnspecified(this DateTime date)
{
if (date.Kind == DateTimeKind.Unspecified)
{
return date;
}
return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, DateTimeKind.Unspecified);
}
/// <summary>
/// Trims the milliseconds off of a datetime
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
[Description("将日期时间缩短毫秒")]
public static DateTime TrimMilliseconds(this DateTime date)
{
return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind);
}
/// <summary>
/// Clears the time.
/// </summary>
/// <param name="dateTime">The date time.</param>
/// <returns></returns>
[Description("清除时间")]
public static DateTime ClearTime(this DateTime dateTime)
{
return dateTime.Subtract(
new TimeSpan(
0,
dateTime.Hour,
dateTime.Minute,
dateTime.Second,
dateTime.Millisecond
)
);
}
}
}

View File

@ -0,0 +1,89 @@
using System;
using System.ComponentModel;
using System.Linq;
namespace JiShe.CollectBus.Common.Extensions
{
/// <summary>
/// Extension methods for <see cref="DayOfWeekExtensions"/>.
/// </summary>
public static class DayOfWeekExtensions
{
/// <summary>
/// Check if a given <see cref="DayOfWeek"/> value is weekend.
/// </summary>
[Description("检查给定值是否为周末")]
public static bool IsWeekend(this DayOfWeek dayOfWeek)
{
return dayOfWeek.IsIn(DayOfWeek.Saturday, DayOfWeek.Sunday);
}
/// <summary>
/// Check if a given <see cref="DayOfWeek"/> value is weekday.
/// </summary>
[Description("检查给定值是否为工作日")]
public static bool IsWeekday(this DayOfWeek dayOfWeek)
{
return dayOfWeek.IsIn(DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday);
}
/// <summary>
/// Finds the NTH week day of a month.
/// </summary>
/// <param name="dayOfWeek">The day of week.</param>
/// <param name="year">The year.</param>
/// <param name="month">The month.</param>
/// <param name="n">The nth instance.</param>
/// <remarks>Compensates for 4th and 5th DayOfWeek of Month</remarks>
[Description("查找一个月的第n周")]
public static DateTime FindNthWeekDayOfMonth(this DayOfWeek dayOfWeek, int year, int month, int n)
{
if (n < 1 || n > 5)
{
throw new ArgumentOutOfRangeException(nameof(n));
}
var y = 0;
var daysOfMonth = DateTimeExtensions.DaysOfMonth(year, month);
// compensate for "last DayOfWeek in month"
var totalInstances = dayOfWeek.TotalInstancesInMonth(year, month);
if (n == 5 && n > totalInstances)
n = 4;
var foundDate = daysOfMonth
.Where(date => dayOfWeek.Equals(date.DayOfWeek))
.OrderBy(date => date)
.Select(x => new { n = ++y, date = x })
.Where(x => x.n.Equals(n)).Select(x => x.date).First(); //black magic wizardry
return foundDate;
}
/// <summary>
/// Finds the total number of instances of a specific DayOfWeek in a month.
/// </summary>
/// <param name="dayOfWeek">The day of week.</param>
/// <param name="year">The year.</param>
/// <param name="month">The month.</param>
/// <returns></returns>
[Description("获取一个月内特定DayOfWeek的实例总数")]
public static int TotalInstancesInMonth(this DayOfWeek dayOfWeek, int year, int month)
{
return DateTimeExtensions.DaysOfMonth(year, month).Count(date => dayOfWeek.Equals(date.DayOfWeek));
}
/// <summary>
/// Gets the total number of instances of a specific DayOfWeek in a month.
/// </summary>
/// <param name="dayOfWeek">The day of week.</param>
/// <param name="dateTime">The date in a month.</param>
/// <returns></returns>
[Description("获取一个月内特定DayOfWeek的实例总数")]
public static int TotalInstancesInMonth(this DayOfWeek dayOfWeek, DateTime dateTime)
{
return dayOfWeek.TotalInstancesInMonth(dateTime.Year, dateTime.Month);
}
}
}

View File

@ -0,0 +1,128 @@
using System.ComponentModel;
using System.Text.RegularExpressions;
namespace JiShe.CollectBus.Common.Extensions
{
public static class DecimalOrIntExtensions
{
/// <summary>Converts to chinese amount.</summary>
/// <param name="number">The number.</param>
/// <returns>
/// <br />
/// </returns>
[Description("换算成中文金额")]
public static string ToChineseAmount(this decimal number)
{
return BuildChineseAmount(number);
}
/// <summary>Converts to chinese amount.</summary>
/// <param name="number">The number.</param>
/// <returns>
/// <br />
/// </returns>
public static string ToChineseAmount(this int number)
{
return BuildChineseAmount(number);
}
/// <summary>Determines whether the specified minimum is between.</summary>
/// <param name="number">The number.</param>
/// <param name="min">The minimum.</param>
/// <param name="max">The maximum.</param>
/// <returns>
/// <c>true</c> if the specified minimum is between; otherwise, <c>false</c>.</returns>
[Description("判断值是否介于两者之间")]
public static bool IsBetween(this decimal number, decimal min, decimal max)
{
return number >= min && number <= max;
}
/// <summary>Determines whether the specified minimum is between.</summary>
/// <param name="number">The number.</param>
/// <param name="min">The minimum.</param>
/// <param name="max">The maximum.</param>
/// <returns>
/// <c>true</c> if the specified minimum is between; otherwise, <c>false</c>.</returns>
public static bool IsBetween(this int number, int min, int max)
{
return number >= min && number <= max;
}
/// <summary>Determines whether the specified minimum is between.</summary>
/// <param name="number">The number.</param>
/// <param name="min">The minimum.</param>
/// <param name="max">The maximum.</param>
/// <returns>
/// <c>true</c> if the specified minimum is between; otherwise, <c>false</c>.</returns>
public static bool IsBetween(this float number, float min, float max)
{
return number >= min && number <= max;
}
/// <summary>Determines whether the specified minimum is between.</summary>
/// <param name="number">The number.</param>
/// <param name="min">The minimum.</param>
/// <param name="max">The maximum.</param>
/// <returns>
/// <c>true</c> if the specified minimum is between; otherwise, <c>false</c>.</returns>
public static bool IsBetween(this double number, double min, double max)
{
return number >= min && number <= max;
}
/// <summary>Determines whether the specified minimum is between.</summary>
/// <param name="number">The number.</param>
/// <param name="min">The minimum.</param>
/// <param name="max">The maximum.</param>
/// <returns>
/// <c>true</c> if the specified minimum is between; otherwise, <c>false</c>.</returns>
public static bool IsBetween(this decimal? number, decimal min, decimal max)
{
return number.HasValue && (number >= min && number <= max);
}
/// <summary>Determines whether the specified minimum is between.</summary>
/// <param name="number">The number.</param>
/// <param name="min">The minimum.</param>
/// <param name="max">The maximum.</param>
/// <returns>
/// <c>true</c> if the specified minimum is between; otherwise, <c>false</c>.</returns>
public static bool IsBetween(this int? number, int min, int max)
{
return number.HasValue && (number >= min && number <= max);
}
/// <summary>Determines whether the specified minimum is between.</summary>
/// <param name="number">The number.</param>
/// <param name="min">The minimum.</param>
/// <param name="max">The maximum.</param>
/// <returns>
/// <c>true</c> if the specified minimum is between; otherwise, <c>false</c>.</returns>
public static bool IsBetween(this float? number, float min, float max)
{
return number.HasValue && (number >= min && number <= max);
}
/// <summary>Determines whether the specified minimum is between.</summary>
/// <param name="number">The number.</param>
/// <param name="min">The minimum.</param>
/// <param name="max">The maximum.</param>
/// <returns>
/// <c>true</c> if the specified minimum is between; otherwise, <c>false</c>.</returns>
public static bool IsBetween(this double? number, double min, double max)
{
return number.HasValue && (number >= min && number <= max);
}
private static string BuildChineseAmount(decimal number)
{
var s = number.ToString("#L#E#D#C#K#E#D#C#J#E#D#C#I#E#D#C#H#E#D#C#G#E#D#C#F#E#D#C#.0B0A");
var d = Regex.Replace(s,
@"((?<=-|^)[^1-9]*)|((?'z'0)[0A-E]*((?=[1-9])|(?'-z'(?=[F-L\.]|$))))|((?'b'[F-L])(?'z'0)[0A-L]*((?=[1-9])|(?'-z'(?=[\.]|$))))",
"${b}${z}");
var r = Regex.Replace(d, ".", m => "负元空零壹贰叁肆伍陆柒捌玖空空空空空空空分角拾佰仟万亿兆京垓秭穰"[m.Value[0] - '-'].ToString());
return r;
}
}
}

View File

@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace JiShe.CollectBus.Common.Extensions
{
/// <summary>
/// Extension methods for Dictionary.
/// </summary>
public static class DictionaryExtensions
{
/// <summary>
/// This method is used to try to get a value in a dictionary if it does exists.
/// </summary>
/// <typeparam name="T">Type of the value</typeparam>
/// <param name="dictionary">The collection object</param>
/// <param name="key">Key</param>
/// <param name="value">Value of the key (or default value if key not exists)</param>
/// <returns>True if key does exists in the dictionary</returns>
internal static bool TryGetValue<T>(this IDictionary<string, object> dictionary, string key, out T value)
{
object valueObj;
if (dictionary.TryGetValue(key, out valueObj) && valueObj is T)
{
value = (T)valueObj;
return true;
}
value = default(T);
return false;
}
/// <summary>
/// Gets a value from the dictionary with given key. Returns default value if can not find.
/// </summary>
/// <param name="dictionary">Dictionary to check and get</param>
/// <param name="key">Key to find the value</param>
/// <typeparam name="TKey">Type of the key</typeparam>
/// <typeparam name="TValue">Type of the value</typeparam>
/// <returns>Value if found, default if can not found.</returns>
[Description("从字典中获取具有给定键的值,如果找不到,则返回默认值")]
public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
{
TValue obj;
return dictionary.TryGetValue(key, out obj) ? obj : default(TValue);
}
/// <summary>
/// Gets a value from the dictionary with given key. Add value if can not find.
/// </summary>
/// <param name="dictionary">Dictionary to check and get</param>
/// <param name="key">Key to find the value</param>
/// <param name="factory">A factory method used to create the value if not found in the dictionary</param>
/// <typeparam name="TKey">Type of the key</typeparam>
/// <typeparam name="TValue">Type of the value</typeparam>
/// <returns>Value if found, default if can not found.</returns>
[Description("从字典中获取具有给定键的值,如果找不到,则添加")]
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> factory)
{
TValue obj;
if (dictionary.TryGetValue(key, out obj))
{
return obj;
}
return dictionary[key] = factory(key);
}
/// <summary>
/// Gets a value from the dictionary with given key. Add value if can not find.
/// </summary>
/// <param name="dictionary">Dictionary to check and get</param>
/// <param name="key">Key to find the value</param>
/// <param name="factory">A factory method used to create the value if not found in the dictionary</param>
/// <typeparam name="TKey">Type of the key</typeparam>
/// <typeparam name="TValue">Type of the value</typeparam>
/// <returns>Value if found, default if can not found.</returns>
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TValue> factory)
{
return dictionary.GetOrAdd(key, k => factory());
}
}
}

View File

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
namespace JiShe.CollectBus.Common.Extensions
{
/// <summary>
/// Extension methods for <see cref="IEnumerable{T}"/>.
/// </summary>
public static class EnumerableExtensions
{
/// <summary>
/// Concatenates the members of a constructed <see cref="IEnumerable{T}"/> collection of type System.String, using the specified separator between each member.
/// This is a shortcut for string.Join(...)
/// </summary>
/// <param name="source">A collection that contains the strings to concatenate.</param>
/// <param name="separator">The string to use as a separator. separator is included in the returned string only if values has more than one element.</param>
/// <returns>A string that consists of the members of values delimited by the separator string. If values has no members, the method returns System.String.Empty.</returns>
[Description("Enumerable转换String")]
public static string JoinAsString(this IEnumerable<string> source, string separator)
{
return string.Join(separator, source);
}
/// <summary>
/// Concatenates the members of a collection, using the specified separator between each member.
/// This is a shortcut for string.Join(...)
/// </summary>
/// <param name="source">A collection that contains the objects to concatenate.</param>
/// <param name="separator">The string to use as a separator. separator is included in the returned string only if values has more than one element.</param>
/// <typeparam name="T">The type of the members of values.</typeparam>
/// <returns>A string that consists of the members of values delimited by the separator string. If values has no members, the method returns System.String.Empty.</returns>
public static string JoinAsString<T>(this IEnumerable<T> source, string separator)
{
return string.Join(separator, source);
}
/// <summary>
/// Filters a <see cref="IEnumerable{T}"/> by given predicate if given condition is true.
/// </summary>
/// <param name="source">Enumerable to apply filtering</param>
/// <param name="condition">A boolean value</param>
/// <param name="predicate">Predicate to filter the enumerable</param>
/// <returns>Filtered or not filtered enumerable based on <paramref name="condition"/></returns>
[Description("Enumerable筛选")]
public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, bool condition, Func<T, bool> predicate)
{
return condition
? source.Where(predicate)
: source;
}
/// <summary>
/// Filters a <see cref="IEnumerable{T}"/> by given predicate if given condition is true.
/// </summary>
/// <param name="source">Enumerable to apply filtering</param>
/// <param name="condition">A boolean value</param>
/// <param name="predicate">Predicate to filter the enumerable</param>
/// <returns>Filtered or not filtered enumerable based on <paramref name="condition"/></returns>
public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, bool condition, Func<T, int, bool> predicate)
{
return condition
? source.Where(predicate)
: source;
}
}
}

View File

@ -0,0 +1,56 @@
using System;
using System.ComponentModel;
namespace JiShe.CollectBus.Common.Extensions
{
/// <summary>
/// Extension methods for <see cref="EventHandler"/>.
/// </summary>
public static class EventHandlerExtensions
{
/// <summary>
/// Raises given event safely with given arguments.
/// </summary>
/// <param name="eventHandler">The event handler</param>
/// <param name="sender">Source of the event</param>
[Description("使用给定参数安全引发给定事件")]
public static void InvokeSafely(this EventHandler eventHandler, object sender)
{
eventHandler.InvokeSafely(sender, EventArgs.Empty);
}
/// <summary>
/// Raises given event safely with given arguments.
/// </summary>
/// <param name="eventHandler">The event handler</param>
/// <param name="sender">Source of the event</param>
/// <param name="e">Event argument</param>
public static void InvokeSafely(this EventHandler eventHandler, object sender, EventArgs e)
{
if (eventHandler == null)
{
return;
}
eventHandler(sender, e);
}
/// <summary>
/// Raises given event safely with given arguments.
/// </summary>
/// <typeparam name="TEventArgs">Type of the <see cref="EventArgs"/></typeparam>
/// <param name="eventHandler">The event handler</param>
/// <param name="sender">Source of the event</param>
/// <param name="e">Event argument</param>
public static void InvokeSafely<TEventArgs>(this EventHandler<TEventArgs> eventHandler, object sender, TEventArgs e)
where TEventArgs : EventArgs
{
if (eventHandler == null)
{
return;
}
eventHandler(sender, e);
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.ComponentModel;
using System.Runtime.ExceptionServices;
namespace JiShe.CollectBus.Common.Extensions
{
/// <summary>
/// Extension methods for <see cref="Exception"/> class.
/// </summary>
public static class ExceptionExtensions
{
/// <summary>
/// Uses <see cref="ExceptionDispatchInfo.Capture"/> method to re-throws exception
/// while preserving stack trace.
/// </summary>
/// <param name="exception">Exception to be re-thrown</param>
[Description("ÖØÐÂÒý·¢Òì³£")]
public static void ReThrow(this Exception exception)
{
ExceptionDispatchInfo.Capture(exception).Throw();
}
}
}

View File

@ -0,0 +1,33 @@
using System.ComponentModel;
using System.Net;
using System.Net.Http.Headers;
using System.Text;
using System.Web;
namespace JiShe.CollectBus.Common.Extensions
{
public static class HttpResponseExtensions
{
/// <summary>
/// Sets the cookie.
/// </summary>
/// <param name="headers">The headers.</param>
/// <param name="cookie">The cookie.</param>
[Description("设置请求头")]
public static void SetCookie(this HttpResponseHeaders headers, Cookie cookie)
{
var cookieBuilder = new StringBuilder(HttpUtility.UrlEncode(cookie.Name) + "=" + HttpUtility.UrlEncode(cookie.Value));
if (cookie.HttpOnly)
{
cookieBuilder.Append("; HttpOnly");
}
if (cookie.Secure)
{
cookieBuilder.Append("; Secure");
}
headers.Add("Set-Cookie", cookieBuilder.ToString());
}
}
}

View File

@ -0,0 +1,366 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using JetBrains.Annotations;
namespace JiShe.CollectBus.Common.Extensions
{
/// <summary>
/// Extension methods for <see cref="IList{T}"/>.
/// </summary>
public static class ListExtensions
{
/// <summary>
/// Inserts the range.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="index">The index.</param>
/// <param name="items">The items.</param>
[Description("插入多个")]
public static void InsertRange<T>(this IList<T> source, int index, IEnumerable<T> items)
{
foreach (var item in items)
{
source.Insert(index++, item);
}
}
/// <summary>
/// Finds the index.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="selector">The selector.</param>
/// <returns></returns>
[Description("查找索引")]
public static int FindIndex<T>(this IList<T> source, Predicate<T> selector)
{
for (var i = 0; i < source.Count; ++i)
{
if (selector(source[i]))
{
return i;
}
}
return -1;
}
/// <summary>
/// Adds the first.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="item">The item.</param>
[Description("在开头插入")]
public static void AddFirst<T>(this IList<T> source, T item)
{
source.Insert(0, item);
}
/// <summary>
/// Adds the last.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="item">The item.</param>
[Description("在结尾插入")]
public static void AddLast<T>(this IList<T> source, T item)
{
source.Insert(source.Count, item);
}
/// <summary>
/// Inserts the after.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="existingItem">The existing item.</param>
/// <param name="item">The item.</param>
[Description("在...之后插入")]
public static void InsertAfter<T>(this IList<T> source, T existingItem, T item)
{
var index = source.IndexOf(existingItem);
if (index < 0)
{
source.AddFirst(item);
return;
}
source.Insert(index + 1, item);
}
/// <summary>
/// Inserts the after.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="selector">The selector.</param>
/// <param name="item">The item.</param>
public static void InsertAfter<T>(this IList<T> source, Predicate<T> selector, T item)
{
var index = source.FindIndex(selector);
if (index < 0)
{
source.AddFirst(item);
return;
}
source.Insert(index + 1, item);
}
/// <summary>
/// Inserts the before.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="existingItem">The existing item.</param>
/// <param name="item">The item.</param>
[Description("在...之前插入")]
public static void InsertBefore<T>(this IList<T> source, T existingItem, T item)
{
var index = source.IndexOf(existingItem);
if (index < 0)
{
source.AddLast(item);
return;
}
source.Insert(index, item);
}
/// <summary>
/// Inserts the before.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="selector">The selector.</param>
/// <param name="item">The item.</param>
public static void InsertBefore<T>(this IList<T> source, Predicate<T> selector, T item)
{
var index = source.FindIndex(selector);
if (index < 0)
{
source.AddLast(item);
return;
}
source.Insert(index, item);
}
/// <summary>
/// Replaces the while.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="selector">The selector.</param>
/// <param name="item">The item.</param>
[Description("替换")]
public static void ReplaceWhile<T>(this IList<T> source, Predicate<T> selector, T item)
{
for (int i = 0; i < source.Count; i++)
{
if (selector(source[i]))
{
source[i] = item;
}
}
}
/// <summary>
/// Replaces the while.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="selector">The selector.</param>
/// <param name="itemFactory">The item factory.</param>
public static void ReplaceWhile<T>(this IList<T> source, Predicate<T> selector, Func<T, T> itemFactory)
{
for (int i = 0; i < source.Count; i++)
{
var item = source[i];
if (selector(item))
{
source[i] = itemFactory(item);
}
}
}
/// <summary>
/// Replaces the one.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="selector">The selector.</param>
/// <param name="item">The item.</param>
[Description("替换")]
public static void ReplaceOne<T>(this IList<T> source, Predicate<T> selector, T item)
{
for (int i = 0; i < source.Count; i++)
{
if (selector(source[i]))
{
source[i] = item;
return;
}
}
}
/// <summary>
/// Replaces the one.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="selector">The selector.</param>
/// <param name="itemFactory">The item factory.</param>
public static void ReplaceOne<T>(this IList<T> source, Predicate<T> selector, Func<T, T> itemFactory)
{
for (int i = 0; i < source.Count; i++)
{
var item = source[i];
if (selector(item))
{
source[i] = itemFactory(item);
return;
}
}
}
/// <summary>
/// Replaces the one.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="item">The item.</param>
/// <param name="replaceWith">The replace with.</param>
public static void ReplaceOne<T>(this IList<T> source, T item, T replaceWith)
{
for (int i = 0; i < source.Count; i++)
{
if (Comparer<T>.Default.Compare(source[i], item) == 0)
{
source[i] = replaceWith;
return;
}
}
}
/// <summary>
/// Moves the item.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="selector">The selector.</param>
/// <param name="targetIndex">Index of the target.</param>
/// <exception cref="IndexOutOfRangeException">targetIndex should be between 0 and " + (source.Count - 1)</exception>
[Description("移动项")]
public static void MoveItem<T>(this List<T> source, Predicate<T> selector, int targetIndex)
{
if (!targetIndex.IsBetween(0, source.Count - 1))
{
throw new IndexOutOfRangeException("targetIndex should be between 0 and " + (source.Count - 1));
}
var currentIndex = source.FindIndex(0, selector);
if (currentIndex == targetIndex)
{
return;
}
var item = source[currentIndex];
source.RemoveAt(currentIndex);
source.Insert(targetIndex, item);
}
/// <summary>
/// Gets the or add.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">The source.</param>
/// <param name="selector">The selector.</param>
/// <param name="factory">The factory.</param>
/// <returns></returns>
[Description("获取并添加")]
public static T GetOrAdd<T>([NotNull] this IList<T> source, Func<T, bool> selector, Func<T> factory)
{
var item = source.FirstOrDefault(selector);
if (item == null)
{
item = factory();
source.Add(item);
}
return item;
}
/// <summary>
/// Sort a list by a topological sorting, which consider their dependencies.
/// </summary>
/// <typeparam name="T">The type of the members of values.</typeparam>
/// <param name="source">A list of objects to sort</param>
/// <param name="getDependencies">Function to resolve the dependencies</param>
/// <param name="comparer">Equality comparer for dependencies </param>
/// <returns>
/// Returns a new list ordered by dependencies.
/// If A depends on B, then B will come before than A in the resulting list.
/// </returns>
[Description("通过topological排序对列表进行排序topological排序考虑了它们之间的依赖关系")]
public static List<T> SortByDependencies<T>(
this IEnumerable<T> source,
Func<T, IEnumerable<T>> getDependencies,
IEqualityComparer<T> comparer = null)
{
var sorted = new List<T>();
var visited = new Dictionary<T, bool>(comparer);
foreach (var item in source)
{
SortByDependenciesVisit(item, getDependencies, sorted, visited);
}
return sorted;
}
/// <summary>
///
/// </summary>
/// <typeparam name="T">The type of the members of values.</typeparam>
/// <param name="item">Item to resolve</param>
/// <param name="getDependencies">Function to resolve the dependencies</param>
/// <param name="sorted">List with the sortet items</param>
/// <param name="visited">Dictionary with the visited items</param>
private static void SortByDependenciesVisit<T>(T item, Func<T, IEnumerable<T>> getDependencies, List<T> sorted,
Dictionary<T, bool> visited)
{
bool inProcess;
var alreadyVisited = visited.TryGetValue(item, out inProcess);
if (alreadyVisited)
{
if (inProcess)
{
throw new ArgumentException("Cyclic dependency found! Item: " + item);
}
}
else
{
visited[item] = true;
var dependencies = getDependencies(item);
if (dependencies != null)
{
foreach (var dependency in dependencies)
{
SortByDependenciesVisit(dependency, getDependencies, sorted, visited);
}
}
visited[item] = false;
sorted.Add(item);
}
}
}
}

View File

@ -0,0 +1,68 @@
using System;
namespace JiShe.CollectBus.Common.Extensions
{
/// <summary>
/// Extension methods to make locking easier.
/// </summary>
public static class LockExtensions
{
/// <summary>
/// Executes given <paramref name="action"/> by locking given <paramref name="source"/> object.
/// </summary>
/// <param name="source">Source object (to be locked)</param>
/// <param name="action">Action (to be executed)</param>
public static void Locking(this object source, Action action)
{
lock (source)
{
action();
}
}
/// <summary>
/// Executes given <paramref name="action"/> by locking given <paramref name="source"/> object.
/// </summary>
/// <typeparam name="T">Type of the object (to be locked)</typeparam>
/// <param name="source">Source object (to be locked)</param>
/// <param name="action">Action (to be executed)</param>
public static void Locking<T>(this T source, Action<T> action) where T : class
{
lock (source)
{
action(source);
}
}
/// <summary>
/// Executes given <paramref name="func"/> and returns it's value by locking given <paramref name="source"/> object.
/// </summary>
/// <typeparam name="TResult">Return type</typeparam>
/// <param name="source">Source object (to be locked)</param>
/// <param name="func">Function (to be executed)</param>
/// <returns>Return value of the <paramref name="func"/></returns>
public static TResult Locking<TResult>(this object source, Func<TResult> func)
{
lock (source)
{
return func();
}
}
/// <summary>
/// Executes given <paramref name="func"/> and returns it's value by locking given <paramref name="source"/> object.
/// </summary>
/// <typeparam name="T">Type of the object (to be locked)</typeparam>
/// <typeparam name="TResult">Return type</typeparam>
/// <param name="source">Source object (to be locked)</param>
/// <param name="func">Function (to be executed)</param>
/// <returns>Return value of the <paramnref name="func"/></returns>
public static TResult Locking<T, TResult>(this T source, Func<T, TResult> func) where T : class
{
lock (source)
{
return func(source);
}
}
}
}

View File

@ -0,0 +1,154 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
namespace JiShe.CollectBus.Common.Extensions
{
public static class ObjectExtensions
{
/// <summary>Gets the description.</summary>
/// <param name="customAttributeProvider">The custom attribute provider.</param>
/// <returns>
/// <br />
/// </returns>
[Description("获取Description")]
public static string GetDescription(this ICustomAttributeProvider customAttributeProvider)
{
var des = string.Empty;
var desAttribute = customAttributeProvider.GetAttribute<DescriptionAttribute>();
if (desAttribute != null) des = desAttribute.Description;
return des;
}
/// <summary>Determines whether this instance is required.</summary>
/// <param name="propertyInfo">The property information.</param>
/// <returns>
/// <c>true</c> if the specified property information is required; otherwise, <c>false</c>.</returns>
[Description("是否必填")]
public static bool IsRequired(this PropertyInfo propertyInfo)
{
if (propertyInfo.GetAttribute<RequiredAttribute>(true) != null) return true;
//Boolean、Byte、SByte、Int16、UInt16、Int32、UInt32、Int64、UInt64、Char、Double、Single
if (propertyInfo.PropertyType.IsPrimitive) return true;
switch (propertyInfo.PropertyType.Name)
{
case "DateTime":
case "Decimal":
return true;
}
return false;
}
/// <summary>Gets the attribute.</summary>
/// <typeparam name="T"></typeparam>
/// <param name="assembly">The assembly.</param>
/// <param name="inherit">if set to <c>true</c> [inherit].</param>
/// <returns>
/// <br />
/// </returns>
[Description("获取属性")]
public static T GetAttribute<T>(this ICustomAttributeProvider assembly, bool inherit = false)
where T : Attribute
{
return assembly
.GetCustomAttributes(typeof(T), inherit)
.OfType<T>()
.FirstOrDefault();
}
/// <summary>
/// Enums to list.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
/// <exception cref="ArgumentException">T must be of type System.Enum</exception>
[Description("枚举转换为集合")]
public static List<T> EnumToList<T>()
{
var enumType = typeof(T);
if (enumType.BaseType != typeof(Enum))
throw new ArgumentException("T must be of type System.Enum");
var enumValArray = Enum.GetValues(enumType);
var enumValList = new List<T>(enumValArray.Length);
enumValList.AddRange(from int val in enumValArray select (T)Enum.Parse(enumType, val.ToString()));
return enumValList;
}
/// <summary>
/// Enums to dictionary.
/// </summary>
/// <param name="t">The t.</param>
/// <returns></returns>
/// <exception cref="NullReferenceException"></exception>
/// <exception cref="InvalidCastException">object is not an Enumeration</exception>
[Description("枚举转换为字典")]
public static IDictionary<string, int> EnumToDictionary(this Type t)
{
if (t == null) throw new NullReferenceException();
if (!t.IsEnum) throw new InvalidCastException("object is not an Enumeration");
var names = Enum.GetNames(t);
var values = Enum.GetValues(t);
return (from i in Enumerable.Range(0, names.Length)
select new { Key = names[i], Value = (int)values.GetValue(i) }).ToDictionary(k => k.Key, k => k.Value);
}
/// <summary>
/// Used to simplify and beautify casting an object to a type.
/// </summary>
/// <typeparam name="T">Type to be casted</typeparam>
/// <param name="obj">Object to cast</param>
/// <returns>Casted object</returns>
public static T As<T>(this object obj)
where T : class
{
return (T)obj;
}
/// <summary>
/// Converts given object to a value or enum type using <see cref="Convert.ChangeType(object,TypeCode)"/> or <see cref="Enum.Parse(Type,string)"/> method.
/// </summary>
/// <param name="obj">Object to be converted</param>
/// <typeparam name="T">Type of the target object</typeparam>
/// <returns>Converted object</returns>
public static T To<T>(this object obj)
where T : struct
{
if (typeof(T) == typeof(Guid) || typeof(T) == typeof(TimeSpan))
{
return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(obj.ToString());
}
if (typeof(T).IsEnum)
{
if (Enum.IsDefined(typeof(T), obj))
{
return (T)Enum.Parse(typeof(T), obj.ToString());
}
else
{
throw new ArgumentException($"Enum type undefined '{obj}'.");
}
}
return (T)Convert.ChangeType(obj, typeof(T), CultureInfo.InvariantCulture);
}
/// <summary>
/// Check if an item is in a list.
/// </summary>
/// <param name="item">Item to check</param>
/// <param name="list">List of items</param>
/// <typeparam name="T">Type of the items</typeparam>
public static bool IsIn<T>(this T item, params T[] list)
{
return list.Contains(item);
}
}
}

View File

@ -0,0 +1,59 @@
using System.ComponentModel;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace JiShe.CollectBus.Common.Extensions
{
public static class StreamExtensions
{
/// <summary>
/// Gets all bytes.
/// </summary>
/// <param name="stream">The stream.</param>
/// <returns></returns>
[Description("获取字节数组")]
public static byte[] GetAllBytes(this Stream stream)
{
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
/// <summary>
/// Gets all bytes asynchronous.
/// </summary>
/// <param name="stream">The stream.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public static async Task<byte[]> GetAllBytesAsync(this Stream stream, CancellationToken cancellationToken = default)
{
using (var memoryStream = new MemoryStream())
{
stream.Position = 0;
await stream.CopyToAsync(memoryStream, cancellationToken);
return memoryStream.ToArray();
}
}
/// <summary>
/// Copies to asynchronous.
/// </summary>
/// <param name="stream">The stream.</param>
/// <param name="destination">The destination.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
[Description("复制")]
public static Task CopyToAsync(this Stream stream, Stream destination, CancellationToken cancellationToken)
{
stream.Position = 0;
return stream.CopyToAsync(
destination,
81920, //this is already the default value, but needed to set to be able to pass the cancellationToken
cancellationToken
);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,64 @@
using System;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
namespace JiShe.CollectBus.Common.Extensions
{
public static class XmlExtensions
{
/// <summary>
/// Froms the XML.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="xml">The XML.</param>
/// <returns></returns>
[Description("将XML转换为Object")]
public static object FromXml<T>(this string xml) where T : new()
{
using (var sr = new StringReader(xml))
{
var xmlSerializer = new XmlSerializer(typeof(T));
return (T)xmlSerializer.Deserialize(sr);
}
}
/// <summary>
/// Deserializes the specified XML document.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="xmlDocument">The XML document.</param>
/// <returns></returns>
[Description("反序列化指定的XML文档")]
public static T Deserialize<T>(this XDocument xmlDocument)
{
var xmlSerializer = new XmlSerializer(typeof(T));
using (var reader = xmlDocument.CreateReader())
return (T)xmlSerializer.Deserialize(reader);
}
/// <summary>
/// Gets an attribute's value from an Xml node.
/// </summary>
/// <param name="node">The Xml node</param>
/// <param name="attributeName">Attribute name</param>
/// <returns>Value of the attribute</returns>
[Description("从Xml节点获取属性的值")]
public static string GetAttributeValueOrNull(this XmlNode node, string attributeName)
{
if (node.Attributes == null || node.Attributes.Count <= 0)
{
throw new Exception(node.Name + " node has not " + attributeName + " attribute");
}
return node.Attributes
.Cast<XmlAttribute>()
.Where(attr => attr.Name == attributeName)
.Select(attr => attr.Value)
.FirstOrDefault();
}
}
}

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace JiShe.CollectBus.Common.Helpers
{
public static class TypeHelper
{
public static bool IsFunc(object obj)
{
if (obj == null)
{
return false;
}
var type = obj.GetType();
if (!type.GetTypeInfo().IsGenericType)
{
return false;
}
return type.GetGenericTypeDefinition() == typeof(Func<>);
}
public static bool IsFunc<TReturn>(object obj)
{
return obj != null && obj.GetType() == typeof(Func<TReturn>);
}
public static bool IsPrimitiveExtendedIncludingNullable(Type type, bool includeEnums = false)
{
if (IsPrimitiveExtended(type, includeEnums))
{
return true;
}
if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
return IsPrimitiveExtended(type.GenericTypeArguments[0], includeEnums);
}
return false;
}
private static bool IsPrimitiveExtended(Type type, bool includeEnums)
{
if (type.GetTypeInfo().IsPrimitive)
{
return true;
}
if (includeEnums && type.GetTypeInfo().IsEnum)
{
return true;
}
return type == typeof(string) ||
type == typeof(decimal) ||
type == typeof(DateTime) ||
type == typeof(DateTimeOffset) ||
type == typeof(TimeSpan) ||
type == typeof(Guid);
}
}
}

View File

@ -5,4 +5,8 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2024.2.0" />
</ItemGroup>
</Project> </Project>

View File

@ -7,12 +7,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="TouchSocket" Version="2.1.5" /> <Compile Remove="Extensions\**" />
<PackageReference Include="TouchSocket.Hosting" Version="2.1.5" /> <EmbeddedResource Remove="Extensions\**" />
<None Remove="Extensions\**" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Extensions\" /> <PackageReference Include="TouchSocket" Version="2.1.5" />
<PackageReference Include="TouchSocket.Hosting" Version="2.1.5" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -10,22 +10,15 @@ namespace JiShe.CollectBus.Core.Plugins
{ {
public async Task OnTcpReceived(ITcpSession client, ReceivedDataEventArgs e) public async Task OnTcpReceived(ITcpSession client, ReceivedDataEventArgs e)
{ {
//TODO:电表: 376.1 645-07 modbus 水表: 118 645-97 //TODO: 电表主站到集中器的协议都是376.1协议集中器下发到电表协议分为645-07和modbus
//TODO: 水表主站到集中器的协议分为118和645-97协议
//TODO: 连接成功时获取档案信息,根据档案信息匹配协议正则获取协议服务进行监听发送
const string protocolType = "StandardProtocol"; const string protocolType = "StandardProtocol";
switch (protocolType)
{
//case "376":
// //todo登录拿到设备信息根据设备信息使用不同的协议解析服务
// break;
//case "645":
// //todo: 直接拿设备信息,根据设备信息使用不同的协议解析服务
// break;
}
var protocolPlugin = serviceProvider.GetKeyedService<IProtocolPlugin>(protocolType); var protocolPlugin = serviceProvider.GetKeyedService<IProtocolPlugin>(protocolType);
client.Logger.Info($"{protocolPlugin?.Get().Name},{protocolPlugin?.Get().RegularExpression}"); client.Logger.Info($"{protocolPlugin?.Get().Name},{protocolPlugin?.Get().RegularExpression}");
//从客户端收到信息 //从客户端收到信息
var messageHexString = Convert.ToHexString(e.ByteBlock.Span); var messageHexString = Convert.ToHexString(e.ByteBlock.Span);
client.Logger.Info($"[TCP] 已从{client.GetIPPort()}接收到信息:{messageHexString}"); client.Logger.Info($"[TCP] 已从{client.GetIPPort()}接收到信息:{messageHexString}");

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JiShe.CollectBus.EntityFrameworkCore.Entities
{
public class EntityBase<TKey> : IEntity<TKey>
{
public TKey Id { get; set; }
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JiShe.CollectBus.EntityFrameworkCore.Entities
{
public class FullAuditedEntity<TKey, TUser> : EntityBase<TKey>, ICreationAudited<TUser>, IModificationAudited<TUser>, IDeletionAudited<TUser>
{
public TUser CreatorId { get; set; }
public DateTime CreationTime { get; set; }
public TUser LastModifierId { get; set; }
public DateTime? LastModificationTime { get; set; }
public TUser DeleterId { get; set; }
public bool IsDeleted { get; set; }
public DateTime? DeletionTime { get; set; }
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JiShe.CollectBus.EntityFrameworkCore.Entities
{
public interface ICreationAudited<TUser> : IHasCreator<TUser>, IHasCreationTime
{
}
public interface IHasCreator<TUser>
{
TUser CreatorId { get; set; }
}
public interface IHasCreationTime
{
DateTime CreationTime { get; set; }
}
}

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JiShe.CollectBus.EntityFrameworkCore.Entities
{
public interface IDeletionAudited<TUser> : IHasDeleter<TUser>, ISoftDelete, IHasDeletionTime
{
}
public interface ISoftDelete
{
bool IsDeleted { get; set; }
}
public interface IHasDeleter<TUser>
{
TUser DeleterId { get; set; }
}
public interface IHasDeletionTime
{
DateTime? DeletionTime { get; set; }
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JiShe.CollectBus.EntityFrameworkCore.Entities
{
public interface IEntity<TKey>
{
TKey Id { get; }
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JiShe.CollectBus.EntityFrameworkCore.Entities
{
public interface IExtendableObject
{
/// <summary>
/// Gets or sets the extension data.
/// </summary>
/// <value>
/// The extension data.
/// </value>
string ExtensionData { get; set; }
}
}

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JiShe.CollectBus.EntityFrameworkCore.Entities
{
public interface IModificationAudited<TUser> : IHasLastModifier<TUser>, IHasLastModificationTime
{
}
public interface IHasLastModifier<TUser>
{
TUser LastModifierId { get; set; }
}
public interface IHasLastModificationTime
{
DateTime? LastModificationTime { get; set; }
}
}

View File

@ -0,0 +1,153 @@
using JiShe.CollectBus.EntityFrameworkCore.Entities;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using JetBrains.Annotations;
using JiShe.CollectBus.Common.Helpers;
using Newtonsoft.Json.Linq;
using Formatting = Newtonsoft.Json.Formatting;
namespace JiShe.CollectBus.EntityFrameworkCore.Extensions
{
public static class ExtendableObjectExtensions
{
public static T GetData<T>(this IExtendableObject extendableObject, string name, bool handleType = false)
{
return extendableObject.GetData<T>(
name,
handleType
? new JsonSerializer { TypeNameHandling = TypeNameHandling.All }
: JsonSerializer.CreateDefault()
);
}
public static T GetData<T>(this IExtendableObject extendableObject, string name, JsonSerializer? jsonSerializer)
{
if (extendableObject.ExtensionData == null)
{
return default(T);
}
var json = JObject.Parse(extendableObject.ExtensionData);
var prop = json[name];
if (prop == null)
{
return default(T);
}
if (TypeHelper.IsPrimitiveExtendedIncludingNullable(typeof(T)))
{
return prop.Value<T>();
}
else
{
return (T)prop.ToObject(typeof(T), jsonSerializer ?? JsonSerializer.CreateDefault());
}
}
public static void SetData<T>(this IExtendableObject extendableObject, string name, T? value, bool handleType = false)
{
extendableObject.SetData(
name,
value,
handleType
? new JsonSerializer { TypeNameHandling = TypeNameHandling.All }
: JsonSerializer.CreateDefault()
);
}
public static void SetData<T>(this IExtendableObject extendableObject, string name, T? value, JsonSerializer? jsonSerializer)
{
if (extendableObject == null)
{
throw new ArgumentNullException(nameof(extendableObject));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (jsonSerializer == null)
{
jsonSerializer = JsonSerializer.CreateDefault();
}
if (extendableObject.ExtensionData == null)
{
if (EqualityComparer<T>.Default.Equals(value, default(T)))
{
return;
}
extendableObject.ExtensionData = "{}";
}
var json = JObject.Parse(extendableObject.ExtensionData);
if (value == null || EqualityComparer<T>.Default.Equals(value, default(T)))
{
if (json[name] != null)
{
json.Remove(name);
}
}
else if (TypeHelper.IsPrimitiveExtendedIncludingNullable(value.GetType()))
{
json[name] = new JValue(value);
}
else
{
json[name] = JToken.FromObject(value, jsonSerializer);
}
var data = json.ToString(Formatting.None);
if (data == "{}")
{
data = null;
}
extendableObject.ExtensionData = data;
}
public static bool RemoveData(this IExtendableObject extendableObject, string name)
{
if (extendableObject == null)
{
throw new ArgumentNullException(nameof(extendableObject));
}
if (extendableObject.ExtensionData == null)
{
return false;
}
var json = JObject.Parse(extendableObject.ExtensionData);
var token = json[name];
if (token == null)
{
return false;
}
json.Remove(name);
var data = json.ToString(Formatting.None);
if (data == "{}")
{
data = null;
}
extendableObject.ExtensionData = data;
return true;
}
}
}

View File

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JiShe.CollectBus.Common\JiShe.CollectBus.Common.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using JiShe.CollectBus.EntityFrameworkCore.Entities;
namespace JiShe.CollectBus.EntityFrameworkCore.Repositories
{
public interface IRepository<TDbContext, TEntity, TPrimaryKey> where TEntity : class, IEntity<TPrimaryKey>
{
IQueryable<TEntity> GetAll(params Expression<Func<TEntity, object>>[] propertySelectors);
IQueryable<TEntity> GetAll(Expression<Func<TEntity, bool>> expression,
params Expression<Func<TEntity, object>>[] propertySelectors);
TEntity Find(TPrimaryKey id);
Task<TEntity> FindAsync(TPrimaryKey id);
TEntity Get(Expression<Func<TEntity, bool>> expression,
params Expression<Func<TEntity, object>>[] propertySelectors);
Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> expression,
params Expression<Func<TEntity, object>>[] propertySelectors);
void Insert(TEntity entity, bool autoSave = true);
Task InsertAsync(TEntity entity, bool autoSave = true);
Task<TPrimaryKey> InsertAndGetIdAsync(TEntity entity, bool autoSave = true);
void InsertList(List<TEntity> entities, bool autoSave = true);
Task InsertListAsync(List<TEntity> entities, bool autoSave = true);
void Update(TEntity entity, bool autoSave = true);
Task UpdateAsync(TEntity entity, bool autoSave = true);
void UpdateList(IEnumerable<TEntity> entities);
Task UpdateListAsync(IEnumerable<TEntity> entities);
void Delete(TPrimaryKey id, bool autoSave = true);
Task DeleteAsync(TPrimaryKey id, bool autoSave = true);
void Delete(TEntity entity, bool autoSave = true);
Task DeleteAsync(TEntity entity, bool autoSave = true);
void HardDelete(TPrimaryKey id, bool autoSave = true);
Task HardDeleteAsync(TPrimaryKey id, bool autoSave = true);
void HardDelete(TEntity entity, bool autoSave = true);
Task HardDeleteAsync(TEntity entity, bool autoSave = true);
}
}

View File

@ -0,0 +1,296 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using JiShe.CollectBus.Common.Extensions;
using JiShe.CollectBus.EntityFrameworkCore.Entities;
using Microsoft.EntityFrameworkCore;
namespace JiShe.CollectBus.EntityFrameworkCore.Repositories
{
public class Repository<TDbContext, TEntity, TPrimaryKey> : IRepository<TDbContext, TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
where TDbContext : DbContext
{
public virtual DbContext DbContext { private set; get; }
public virtual DbSet<TEntity> Table => DbContext.Set<TEntity>();
public Repository(DbContext dbContext)
{
DbContext = dbContext;
}
public virtual IQueryable<TEntity> GetAll(params Expression<Func<TEntity, object>>[] propertySelectors)
{
var query = Table.AsNoTracking();
if (!propertySelectors.IsNullOrEmpty())
{
foreach (var propertySelector in propertySelectors)
{
query = query.Include(propertySelector);
}
}
return query;
}
public virtual IQueryable<TEntity> GetAll(Expression<Func<TEntity, bool>> expression, params Expression<Func<TEntity, object>>[] propertySelectors)
{
var query = Table.Where(expression);
if (!propertySelectors.IsNullOrEmpty())
{
foreach (var propertySelector in propertySelectors)
{
query = query.Include(propertySelector);
}
}
return query;
}
public virtual TEntity Find(TPrimaryKey id)
{
return Table.Find(id);
}
public virtual async Task<TEntity> FindAsync(TPrimaryKey id)
{
return await Table.FindAsync(id);
}
public virtual TEntity Get(Expression<Func<TEntity, bool>> expression, params Expression<Func<TEntity, object>>[] propertySelectors)
{
var query = GetAll();
if (!propertySelectors.IsNullOrEmpty())
{
foreach (var propertySelector in propertySelectors)
{
query = query.Include(propertySelector);
}
return query.FirstOrDefault(expression);
}
return Table.FirstOrDefault(expression);
}
public virtual async Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> expression, params Expression<Func<TEntity, object>>[] propertySelectors)
{
var query = GetAll();
if (!propertySelectors.IsNullOrEmpty())
{
foreach (var propertySelector in propertySelectors)
{
query = query.Include(propertySelector);
}
return await query.FirstOrDefaultAsync(expression);
}
return await Table.FirstOrDefaultAsync(expression);
}
public virtual void Insert(TEntity entity, bool autoSave = true)
{
var hasCreationTime = typeof(IHasCreationTime).IsAssignableFrom(typeof(TEntity));
if (hasCreationTime)
{
((IHasCreationTime)entity).CreationTime = DateTime.Now;
}
((IHasCreationTime)entity).CreationTime = DateTime.Now;
Table.Add(entity);
if (autoSave)
{
DbContext.SaveChanges();
}
}
public virtual async Task InsertAsync(TEntity entity, bool autoSave = true)
{
var hasCreationTime = typeof(IHasCreationTime).IsAssignableFrom(typeof(TEntity));
if (hasCreationTime)
{
((IHasCreationTime)entity).CreationTime = DateTime.Now;
}
await Table.AddAsync(entity);
if (autoSave)
{
await DbContext.SaveChangesAsync();
}
}
public virtual async Task<TPrimaryKey> InsertAndGetIdAsync(TEntity entity, bool autoSave = true)
{
var hasCreationTime = typeof(IHasCreationTime).IsAssignableFrom(typeof(TEntity));
if (hasCreationTime)
{
((IHasCreationTime)entity).CreationTime = DateTime.Now;
}
await Table.AddAsync(entity);
if (autoSave)
{
await DbContext.SaveChangesAsync();
}
return entity.Id;
}
public virtual void InsertList(List<TEntity> entities, bool autoSave = true)
{
var hasCreationTime = typeof(IHasCreationTime).IsAssignableFrom(typeof(TEntity));
if (hasCreationTime)
{
foreach (var entity in entities)
{
((IHasCreationTime)entity).CreationTime = DateTime.Now;
}
}
Table.AddRange(entities);
if (autoSave)
{
DbContext.SaveChanges();
}
}
public virtual async Task InsertListAsync(List<TEntity> entities, bool autoSave = true)
{
var hasCreationTime = typeof(IHasCreationTime).IsAssignableFrom(typeof(TEntity));
if (hasCreationTime)
{
foreach (var entity in entities)
{
((IHasCreationTime)entity).CreationTime = DateTime.Now;
}
}
await Table.AddRangeAsync(entities);
if (autoSave)
{
await DbContext.SaveChangesAsync();
}
}
public virtual void Update(TEntity entity, bool autoSave = true)
{
var hasLastModificationTime = typeof(IHasLastModificationTime).IsAssignableFrom(typeof(TEntity));
if (hasLastModificationTime)
{
((IHasLastModificationTime)entity).LastModificationTime = DateTime.Now;
}
Table.Update(entity);
if (autoSave)
{
DbContext.SaveChanges();
}
}
public virtual async Task UpdateAsync(TEntity entity, bool autoSave = true)
{
var hasLastModificationTime = typeof(IHasLastModificationTime).IsAssignableFrom(typeof(TEntity));
if (hasLastModificationTime)
{
((IHasLastModificationTime)entity).LastModificationTime = DateTime.Now;
}
Table.Update(entity);
if (autoSave)
{
await DbContext.SaveChangesAsync();
}
}
public virtual void UpdateList(IEnumerable<TEntity> entities)
{
Table.UpdateRange(entities);
DbContext.SaveChanges();
}
public virtual async Task UpdateListAsync(IEnumerable<TEntity> entities)
{
Table.UpdateRange(entities);
await DbContext.SaveChangesAsync();
}
public virtual void Delete(TPrimaryKey id, bool autoSave = true)
{
var entity = Find(id);
if (entity == null)
{
throw new ArgumentNullException();
}
Delete(entity, autoSave);
}
public virtual async Task DeleteAsync(TPrimaryKey id, bool autoSave = true)
{
var entity = await FindAsync(id);
if (entity == null)
{
throw new ArgumentNullException();
}
await DeleteAsync(entity, autoSave);
}
public virtual void Delete(TEntity entity, bool autoSave = true)
{
var hasDeletionTime = typeof(IHasDeletionTime).IsAssignableFrom(typeof(TEntity));
if (hasDeletionTime)
{
((IHasDeletionTime)entity).DeletionTime = DateTime.Now;
}
var isDeleteEntity = typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity));
if (isDeleteEntity)
{
((ISoftDelete)entity).IsDeleted = true;
}
Update(entity, autoSave);
}
public virtual async Task DeleteAsync(TEntity entity, bool autoSave = true)
{
var hasDeletionTime = typeof(IHasDeletionTime).IsAssignableFrom(typeof(TEntity));
if (hasDeletionTime)
{
((IHasDeletionTime)entity).DeletionTime = DateTime.Now;
}
var isDeleteEntity = typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity));
if (isDeleteEntity)
{
((ISoftDelete)entity).IsDeleted = true;
}
await UpdateAsync(entity, autoSave);
}
public virtual void HardDelete(TPrimaryKey id, bool autoSave = true)
{
var entity = Find(id);
if (entity == null)
{
throw new ArgumentNullException();
}
HardDelete(entity, autoSave);
}
public async Task HardDeleteAsync(TPrimaryKey id, bool autoSave = true)
{
var entity = await FindAsync(id);
if (entity == null)
{
throw new ArgumentNullException();
}
await HardDeleteAsync(entity, autoSave);
}
public virtual void HardDelete(TEntity entity, bool autoSave = true)
{
Table.Remove(entity);
if (autoSave)
{
DbContext.SaveChanges();
}
}
public virtual async Task HardDeleteAsync(TEntity entity, bool autoSave = true)
{
Table.Remove(entity);
if (autoSave)
{
await DbContext.SaveChangesAsync();
}
}
}
}

View File

@ -4,8 +4,6 @@ using JiShe.CollectBus.Protocol.Contracts.Attributes;
using JiShe.CollectBus.Protocol.Contracts.DependencyInjection; using JiShe.CollectBus.Protocol.Contracts.DependencyInjection;
using JiShe.CollectBus.Protocol.Contracts.Models; using JiShe.CollectBus.Protocol.Contracts.Models;
using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Distributed;
using System.Data;
using System.Net.Sockets;
using TouchSocket.Sockets; using TouchSocket.Sockets;
namespace JiShe.CollectBus.Protocol namespace JiShe.CollectBus.Protocol

View File

@ -17,7 +17,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{3A04FB29-E
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{C7DEC9FB-3F75-4584-85B0-16EA3CB222E5}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "core", "core", "{C7DEC9FB-3F75-4584-85B0-16EA3CB222E5}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.Protocol.Test", "JiShe.CollectBus.Protocol.Test\JiShe.CollectBus.Protocol.Test.csproj", "{289196B4-FFBE-4E40-A3A1-FCFADBE945ED}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiShe.CollectBus.Protocol.Test", "JiShe.CollectBus.Protocol.Test\JiShe.CollectBus.Protocol.Test.csproj", "{289196B4-FFBE-4E40-A3A1-FCFADBE945ED}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiShe.CollectBus.EntityFrameworkCore", "JiShe.CollectBus.EntityFrameworkCore\JiShe.CollectBus.EntityFrameworkCore.csproj", "{16D42BCF-EDB8-4153-B37D-0B10FB6DF36C}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -49,6 +51,10 @@ Global
{289196B4-FFBE-4E40-A3A1-FCFADBE945ED}.Debug|Any CPU.Build.0 = Debug|Any CPU {289196B4-FFBE-4E40-A3A1-FCFADBE945ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{289196B4-FFBE-4E40-A3A1-FCFADBE945ED}.Release|Any CPU.ActiveCfg = Release|Any CPU {289196B4-FFBE-4E40-A3A1-FCFADBE945ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{289196B4-FFBE-4E40-A3A1-FCFADBE945ED}.Release|Any CPU.Build.0 = Release|Any CPU {289196B4-FFBE-4E40-A3A1-FCFADBE945ED}.Release|Any CPU.Build.0 = Release|Any CPU
{16D42BCF-EDB8-4153-B37D-0B10FB6DF36C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{16D42BCF-EDB8-4153-B37D-0B10FB6DF36C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{16D42BCF-EDB8-4153-B37D-0B10FB6DF36C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{16D42BCF-EDB8-4153-B37D-0B10FB6DF36C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -60,6 +66,7 @@ Global
{4468B52D-3AAE-4918-B4D6-E6E8F000825D} = {C7DEC9FB-3F75-4584-85B0-16EA3CB222E5} {4468B52D-3AAE-4918-B4D6-E6E8F000825D} = {C7DEC9FB-3F75-4584-85B0-16EA3CB222E5}
{1D3A5A4E-B977-4E33-A1AF-62508110C3B7} = {C7DEC9FB-3F75-4584-85B0-16EA3CB222E5} {1D3A5A4E-B977-4E33-A1AF-62508110C3B7} = {C7DEC9FB-3F75-4584-85B0-16EA3CB222E5}
{289196B4-FFBE-4E40-A3A1-FCFADBE945ED} = {3A04FB29-EA75-4499-BBF3-AF24C7D46A1D} {289196B4-FFBE-4E40-A3A1-FCFADBE945ED} = {3A04FB29-EA75-4499-BBF3-AF24C7D46A1D}
{16D42BCF-EDB8-4153-B37D-0B10FB6DF36C} = {C7DEC9FB-3F75-4584-85B0-16EA3CB222E5}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {33261859-9CD1-4A43-B181-AB75C247D1CD} SolutionGuid = {33261859-9CD1-4A43-B181-AB75C247D1CD}