first commit

This commit is contained in:
2026-09-02 16:31:50 +08:00
commit a461727193
911 changed files with 692450 additions and 0 deletions
@@ -0,0 +1,8 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=enumerations/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=extensions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=interfaces/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=transferservice/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=transferservice_005Cdownload/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=transferservice_005Cexceptions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=transferservice_005Cupload/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
@@ -0,0 +1,155 @@
using JSMachine.WMS.Infrastructure.Enums;
namespace JSMachine.WMS.Infrastructure.AppConfiguration
{
/// <summary>
/// WMS 运行时配置模型,由配置文件和环境变量绑定生成。
/// </summary>
public class AppSettings
{
/// <summary>
/// 数据库连接字符串
/// </summary>
public string DataBaseCon { get; set; }
/// <summary>
/// /删除前多少天之前的log
/// </summary>
public int DelLogDate { get; set; }
/// <summary>
/// Erp配置
/// </summary>
public ErpConfig ErpConfig { get; set; }
/// <summary>
/// Rcs配置
/// </summary>
public RcsConfig RcsConfig { get; set; }
/// <summary>
/// 提升机配置
/// </summary>
public ElevatorConfig[] ElevatorConfig { get; set; }
/// <summary>
/// 放置模式(0-完全不混放 1-混合模式,优先同批次放一列,没有空库位再混放 2-完全混放模式,不用批次货物放一起)
/// </summary>
public int PlcaementMod { get; set; }
}
/// <summary>
/// Erp配置,此配置项做了冗余,不同的Erp按需配置
/// </summary>
public class ErpConfig
{
/// <summary>
/// Erp类型
/// </summary>
public ErpType ErpType { get; set; }
/// <summary>
/// Erp地址
/// </summary>
public string ErpUrl { get; set; }
/// <summary>
/// Erp服务器IP
/// </summary>
public string ErpIP { get; set; }
/// <summary>
/// 回传Erp前几天数据
/// </summary>
public int ErpUploadBefore { get; set; }
/// <summary>
/// 上传数据,重试次数
/// </summary>
public int RetryNum { get; set; }
/// <summary>
/// 获取原纸信息接口地址
/// </summary>
public string QueryByPaperLabelUrl { get; set; }
/// <summary>
/// 获取原纸信息接口地址(通过幅宽、纸质编码)
/// </summary>
public string QueryByPaperWidthAndCodeUrl { get; set; }
/// <summary>
/// 原纸出库接口地址
/// </summary>
public string PaperStockOutUrl { get; set; }
/// <summary>
/// 残卷回库接口地址
/// </summary>
public string RePaperStockInUrl { get; set; }
/// <summary>
/// AppId
/// </summary>
public string AppId { get; set; }
/// <summary>
/// AppKey
/// </summary>
public string AppKey { get; set; }
/// <summary>
/// PDA扫合格证码获取物料信息
/// </summary>
public string QueryMateriaInforUrl { get; set; }
/// <summary>
/// 生产入库
/// </summary>
public string ProduceInUrl { get; set; }
/// <summary>
/// 生产退库
/// </summary>
public string ProduceOutUrl { get; set; }
/// <summary>
/// 销售出库接口
/// </summary>
public string SaleOutUrl { get; set; }
/// <summary>
/// 用户编号
/// </summary>
public string Userkey { get; set; }
}
/// <summary>
/// Rcs系统配置
/// </summary>
public class RcsConfig
{
/// <summary>
/// RCS 服务基础地址。
/// </summary>
public string RcsUrl { get; set; }
/// <summary>
/// 创建任务Url
/// </summary>
public string CreateTaskUrl { get; set; }
/// <summary>
/// 取消任务Url
/// </summary>
public string CancelTaskUrl { get; set; }
}
/// <summary>
/// 提升机PLC配置
/// </summary>
public class ElevatorConfig
{
/// <summary>
/// 提升机序号(1,2)
/// </summary>
public int ElevatorNo { get; set; }
/// <summary>
/// 提升机PLC的IP
/// </summary>
public string IP { get; set; }
/// <summary>
/// 提升机PLC的端口
/// </summary>
public int Port { get; set; }
}
}
@@ -0,0 +1,20 @@
using JSMachine.WMS.Infrastructure.Enums;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JSMachine.WMS.Infrastructure.Attributes
{
[AttributeUsage(AttributeTargets.Class)]
public class ErpTypeAttribute : Attribute
{
public ErpType ErpType { get; set; }
public ErpTypeAttribute(ErpType erpType)
{
ErpType = erpType;
}
}
}
@@ -0,0 +1,25 @@
using Rougamo;
using Rougamo.Context;
using System.Threading;
namespace JSMachine.WMS.Infrastructure.Attributes
{
/// <summary>
/// 注意,任何使用该标记的项目中均需要安装Rougamo.Fody包,否则属性标记锁将失效
/// </summary>
public class MethodLockedAttribute : MoAttribute
{
private static readonly SemaphoreSlim SemaphoreSlim = new(1);
public override void OnEntry(MethodContext context)
{
SemaphoreSlim.Wait();
}
public override void OnExit(MethodContext context)
{
SemaphoreSlim.Release();
}
}
}
@@ -0,0 +1,15 @@
using JSMachine.WMS.Infrastructure.Enums;
using System;
namespace JSMachine.WMS.Infrastructure.Attributes
{
[AttributeUsage(AttributeTargets.Class)]
public class PmsTypeAttribute : Attribute
{
public PmsType PmsType { get; set; }
public PmsTypeAttribute(PmsType pmsType)
{
PmsType = pmsType;
}
}
}
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JSMachine.WMS.Infrastructure.Enums
{
/// <summary>
/// Erp类型
/// </summary>
public enum ErpType
{
/// <summary>
/// 企望ERP
/// </summary>
Wantit = 0,
/// <summary>
/// 自有IBS
/// </summary>
IBS = 1,
/// <summary>
/// 辰龙Erp
/// </summary>
ChenLong = 2,
/// <summary>
/// 新荣Erp
/// </summary>
XinRong = 3
}
}
@@ -0,0 +1,15 @@
namespace JSMachine.WMS.Infrastructure.Enums
{
public enum PmsType
{
/// <summary>
/// DCS生管
/// </summary>
DCS = 0,
/// <summary>
/// ACS生管
/// </summary>
ACS = 1
}
}
@@ -0,0 +1,17 @@
namespace JSMachine.WMS.Infrastructure.Enums
{
/// <summary>
/// 扫码场景
/// </summary>
public enum ScannerScene
{
/// <summary>
/// 江苏弘晟
/// </summary>
JiangSuHongShen = 0,
/// <summary>
/// 南阳联络
/// </summary>
NanYangLianLuo = 1
}
}
@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JSMachine.WMS.Infrastructure.Extensions
{
public static class DateTimeExtension
{
/// <summary>
/// 获取当日零点
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime GetTodayBegin(this DateTime dateTime)
{
DateTime timeNow = DateTime.Now;
return new DateTime(timeNow.Year, timeNow.Month, timeNow.Day, 0, 0, 0);
}
/// <summary>
/// 获取当日23点59分59秒
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
public static DateTime GetTodayEnd(this DateTime dateTime)
{
DateTime timeNow = DateTime.Now;
return new DateTime(timeNow.Year, timeNow.Month, timeNow.Day, 23, 59, 59);
}
/// <summary>
/// 将秒数转化为时分秒
/// </summary>
/// <param name="duration"></param>
/// <returns></returns>
public static string Sec_to_hms(int duration)
{
TimeSpan ts = new(0, 0, duration);
string str = "";
if (ts.Hours > 0)
{
str = string.Format("{0:00}", ts.Hours) + ":" + string.Format("{0:00}", ts.Minutes) + ":" + string.Format("{0:00}", ts.Seconds);
}
if (ts.Hours == 0 && ts.Minutes > 0)
{
str = "00:" + string.Format("{0:00}", ts.Minutes) + ":" + string.Format("{0:00}", ts.Seconds);
}
if (ts.Hours == 0 && ts.Minutes == 0)
{
str = "00:00:" + string.Format("{0:00}", ts.Seconds);
}
return str;
}
/// <summary>
/// 将秒数转换为分秒
/// </summary>
/// <param name="duration"></param>
/// <returns></returns>
public static string Sec_to_ms(int duration)
{
TimeSpan ts = new(0, 0, duration);
string str = "";
if (ts.Hours == 0 && ts.Minutes > 0)
{
str = string.Format("{0:00}", ts.Minutes) + ":" + string.Format("{0:00}", ts.Seconds);
}
if (ts.Hours == 0 && ts.Minutes == 0)
{
str = "00:" + string.Format("{0:00}", ts.Seconds);
}
return str;
}
}
}
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace JSMachine.WMS.Infrastructure
{
public static class EnumExtension
{
/// <summary>
/// 获取枚举描述属性值
/// </summary>
/// <param name="enum"></param>
/// <returns></returns>
public static string GetDescription(this Enum @enum)
{
Type type = @enum.GetType();
string name = Enum.GetName(type, @enum);
if (string.IsNullOrWhiteSpace(name))
return @enum.ToString();
FieldInfo field = type.GetField(name);
DescriptionAttribute des = field?.GetCustomAttribute<DescriptionAttribute>();
if (des == null)
return @enum.ToString();
return des.Description;
}
}
}
@@ -0,0 +1,43 @@
using System.Linq;
using JSMachine.DCS.Infrastructure;
using JSMachine.WMS.Infrastructure;
// ReSharper disable once CheckNamespace
namespace System.Collections.Generic
{
public static class EnumerableExtensions
{
public static void ForEach<T>(this IEnumerable<T> @this, Action<T> callback, bool immutable = false)
{
Guards.ThrowIfNull(@this, callback);
var collection = immutable ? @this.ToArray() : @this;
foreach (T item in collection)
{
callback(item);
}
}
public static IEnumerable<T> Do<T>(this IEnumerable<T> @this, Action<T> callback)
{
Guards.ThrowIfNull(@this, callback);
foreach (var item in @this)
{
callback?.Invoke(item);
yield return item;
}
}
//public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
//{
// return source == null || source.Count() == 0;
//}
public static bool IsNullOrEmpty(this IList source)
{
return source == null || source.Count == 0;
}
}
}
@@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JSMachine.WMS.Infrastructure
{
public static class GlobalServericeProvidor
{
public static IServiceProvider IServiceProvider { get; private set; }
public static void UseGlobalServiceProvider(this IApplicationBuilder builder)
{
IServiceProvider = builder.ApplicationServices;
}
public static T GetService<T>()
{
return IServiceProvider.GetService<T>();
}
}
}
@@ -0,0 +1,52 @@
using JSMachine.DCS.Infrastructure;
using Newtonsoft.Json;
// ReSharper disable once CheckNamespace
namespace System
{
public static class JsonExtensions
{
public static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto };
public static readonly JsonSerializerSettings JsonDeserializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto };
public static readonly FileLocatorConverter FileLocatorConverter = new FileLocatorConverter();
static JsonExtensions()
{
JsonSerializerSettings.Converters.Add(FileLocatorConverter);
}
public static string ToJson<T>(this T @object, Formatting formatting = Formatting.None, bool specifyRootType = true)
{
var type = @object.GetType();
return typeof(T) != type && specifyRootType
? JsonConvert.SerializeObject(@object, typeof(T), formatting, JsonSerializerSettings)
: JsonConvert.SerializeObject(@object, formatting, JsonSerializerSettings);
}
public static T ToObject<T>(this string json)
{
return !string.IsNullOrWhiteSpace(json)
? JsonConvert.DeserializeObject<T>(json, JsonDeserializerSettings)
: default;
}
}
public class FileLocatorConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var fileLocator = (FileLocator)value;
writer.WriteValue(fileLocator.FullPath);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotSupportedException();
}
public override bool CanConvert(Type objectType) => objectType == typeof(FileLocator);
}
}
@@ -0,0 +1,41 @@
using System;
// ReSharper disable once CheckNamespace
namespace Prism.Logging
{
public static class LoggerFacadeExtensions
{
public static void Error(this ILoggerFacade logger, string message, Exception e = null)
{
logger.Log(GetMessage(message, e), Category.Exception, Priority.High);
}
public static void Warning(this ILoggerFacade logger, string message, Exception e = null)
{
logger.Log(GetMessage(message, e), Category.Warn, Priority.Medium);
}
public static void Info(this ILoggerFacade logger, string message, Exception e = null)
{
logger.Log(GetMessage(message, e), Category.Info, Priority.Low);
}
public static void Debug(this ILoggerFacade logger, string message, Exception e = null)
{
logger.Log(GetMessage(message, e), Category.Debug, Priority.Low);
}
private static string GetMessage(string message, Exception e)
{
message = $"{message}{Environment.NewLine}";
if (e != null)
{
message = $"{message}{e.Message}{Environment.NewLine}" +
$"{e.StackTrace}{Environment.NewLine}";
}
return message;
}
}
}
@@ -0,0 +1,30 @@
// ReSharper disable once CheckNamespace
namespace System
{
public static class ObjectExtensions
{
private const double Tolerance = 1e-6;
public static T CastTo<T>(this object value)
{
return typeof(T).IsValueType && value != null
? (T)Convert.ChangeType(value, typeof(T))
: value is T typeValue ? typeValue : default;
}
public static bool EqualsWithinTolerance(this double @this, double other)
{
return Math.Abs(@this - other) < Tolerance;
}
public static bool GreaterOrEqual(this double @this, double other)
{
return @this > other || @this.EqualsWithinTolerance(other);
}
public static bool LessOrEqual(this double @this, double other)
{
return @this < other || @this.EqualsWithinTolerance(other);
}
}
}
@@ -0,0 +1,38 @@
using System.Runtime.InteropServices;
using System.Security;
namespace System
{
[SuppressUnmanagedCodeSecurity]
public static class SecureStringExtensions
{
public static string AsString(this SecureString @this)
{
if (@this == null || @this.Length == 0)
return string.Empty;
IntPtr bstr = IntPtr.Zero;
try
{
bstr = Marshal.SecureStringToBSTR(@this);
return Marshal.PtrToStringBSTR(bstr);
}
finally
{
if (bstr != IntPtr.Zero)
Marshal.ZeroFreeBSTR(bstr);
}
}
public static SecureString AsSecureString(this string @this)
{
if (string.IsNullOrEmpty(@this))
return new SecureString();
var secureString = new SecureString();
Array.ForEach(@this.ToCharArray(), secureString.AppendChar);
return secureString;
}
}
}
@@ -0,0 +1,78 @@
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using JSMachine.DCS.Infrastructure;
// ReSharper disable once CheckNamespace
namespace System
{
public static class StringExtensions
{
public static string RandomString(int length)
{
var b = new byte[4];
new RNGCryptoServiceProvider().GetBytes(b);
var r = new Random(BitConverter.ToInt32(b, 0));
var ret = string.Empty;
const string str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (var i = 0; i < length; i++)
ret += str.Substring(r.Next(0, str.Length - 1), 1);
return ret;
}
public static string LogId => RandomString(48);
public static string GetMatch(this string text, string p1, string p2)
{
var rg = new Regex("(?<=(" + p1 + "))[.\\s\\S]*?(?=(" + p2 + "))",
RegexOptions.Multiline | RegexOptions.Singleline);
return rg.Match(text).Value;
}
public static bool IsEmailAddress(this string @this)
{
return !string.IsNullOrEmpty(@this) && !string.IsNullOrWhiteSpace(@this); // TODO
}
public static string TrimMiddle(this string @this, int limitLength, string omitPlaceholder = null)
{
const string defaultOmitPlaceholder = "...";
if (omitPlaceholder == null) omitPlaceholder = defaultOmitPlaceholder;
Guards.ThrowIfNot(limitLength >= omitPlaceholder.Length);
if (string.IsNullOrEmpty(@this) || @this.Length <= limitLength) return @this;
if (limitLength == omitPlaceholder.Length) return omitPlaceholder;
var halfLength = (limitLength - omitPlaceholder.Length) / 2;
var bias = (limitLength - omitPlaceholder.Length) % 2;
var firstHalfString = @this.Substring(0, halfLength + bias);
var secondHalfString = @this.Substring(@this.Length - halfLength);
return $"{firstHalfString}{omitPlaceholder}{secondHalfString}";
}
public static string UpperCamelCaseToDelimiterSeparated(this string upperCamelCase)
{
var stringBuilder = new StringBuilder(upperCamelCase.Length, upperCamelCase.Length * 2);
for (int i = 0; i < upperCamelCase.Length; i++)
{
var @char = upperCamelCase[i];
if (char.IsUpper(@char))
{
if (i != 0) stringBuilder.Append('-');
stringBuilder.Append(char.ToLower(@char));
}
else
{
stringBuilder.Append(@char);
}
}
return stringBuilder.ToString();
}
}
}
@@ -0,0 +1,86 @@
using System;
using System.Diagnostics;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
namespace JSMachine.DCS.Infrastructure
{
[DebuggerDisplay("{" + nameof(FullPath) + "}")]
public class FileLocator : IEquatable<FileLocator>
{
/// <summary>
/// Gets a regular expression for splitting the file full path string.
/// In the right case, the group will have four elements:
/// [0]: FullPath
/// [1]: FolderName
/// [2]: FileName
/// [3]: FileExtension
/// </summary>
private static readonly Regex RegexFileLocation = new Regex(@"^([\\/]?(?:\w:)?(?:[^\\/]+?[\\/])*?)([^\\/]+?(?:\.(\w+?))?)?$", RegexOptions.Compiled);
/// <summary>
/// Gets a string representing the full path of the file.
/// </summary>
public string FullPath { get; }
/// <summary>
/// Gets a string representing the folder where the file is located.
/// </summary>
public string FolderPath { get; }
/// <summary>
/// Gets a string representing the file name.
/// </summary>
public string FileName { get; }
/// <summary>
/// Gets a string representing the file extension.
/// </summary>
public string FileExtension { get; }
/// <summary>
/// Initializes a instance of <see cref="FileLocator"/> with specified file full path.
/// </summary>
/// <param name="fileFullPath">A string representing the full path of the file. </param>
public FileLocator(string fileFullPath)
{
var matchResult = RegexFileLocation.Match(fileFullPath);
if (matchResult.Groups == null || matchResult.Groups.Count != 4)
throw new ArgumentException($"The file path is not valid: {fileFullPath}", fileFullPath);
FullPath = matchResult.Groups[0].Value;
var temp = matchResult.Groups[1].Value;
if (!string.IsNullOrEmpty(temp)) FolderPath = temp.Remove(temp.Length - 1); // Remove the "\" or "/" at the end.
FileName = matchResult.Groups[2].Value;
FileExtension = matchResult.Groups[3].Value.ToLower();
}
public override string ToString() => FullPath;
#region Implements Equals
public bool Equals(FileLocator other) => !Equals(other, null) && string.Equals(FullPath, other.FullPath);
public override bool Equals(object obj) => ReferenceEquals(this, obj) || Equals(obj as FileLocator);
public static bool operator ==(FileLocator left, FileLocator right)
{
if ((object)left == null || (object)right == null)
return Equals(left, right);
return left.Equals(right);
}
public static bool operator !=(FileLocator left, FileLocator right) => !(left == right);
public override int GetHashCode() => FullPath != null ? FullPath.GetHashCode() : 0;
#endregion
public static implicit operator FileLocator(string filePath) => string.IsNullOrEmpty(filePath) ? null : new FileLocator(filePath);
public static implicit operator string(FileLocator fileLocation) => fileLocation?.FullPath;
}
}
@@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Rougamo />
</Weavers>
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="Rougamo" minOccurs="0" maxOccurs="1" type="xs:anyType" />
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JSMachine.WMS.Infrastructure.FullTextSearch
{
/// <summary>
/// 全文检索忽略字段标记
/// </summary>
public class FullTextSearchIgnoreAttribute : Attribute
{
}
}
@@ -0,0 +1,95 @@
using JSMachine.WMS.Infrastructure.LambdaHelp;
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace JSMachine.WMS.Infrastructure.FullTextSearch
{
/// <summary>
/// 全文检索表达式目录树辅助类
/// </summary>
public static class FulleTextSearchHelper<T> where T : class, new()
{
private static PropertyInfo[] Properties = typeof(T).GetProperties();
/// <summary>
/// 构建全文检索表达式目录树(精确匹配)
/// </summary>
public static Expression<Func<T, bool>> BuildFullTextSearchEqualExpression(object keyWords)
{
if (keyWords == null || string.IsNullOrEmpty(keyWords.ToString()))
{
return ExpressionTreeHelper<T>.True();
}
Expression<Func<T, bool>> initTree = ExpressionTreeHelper<T>.False();
foreach (PropertyInfo propertyInfo in Properties)
{
FullTextSearchIgnoreAttribute ignoreAttrbute = propertyInfo
.GetCustomAttributes()
.FirstOrDefault(attribute => attribute is FullTextSearchIgnoreAttribute)
as FullTextSearchIgnoreAttribute;
if (ignoreAttrbute == null)
{
Expression<Func<T, bool>> express = ExpressionTreeHelper<T>.CreateEqual(propertyInfo.Name, keyWords);
initTree = initTree.Or(express);
}
}
return initTree;
}
/// <summary>
/// 构建全文检索表达式目录树(模糊匹配)
/// </summary>
public static Expression<Func<T, bool>> BuildFullTextSearchLikeExpression(object keyWords)
{
if (keyWords == null || string.IsNullOrEmpty(keyWords.ToString()))
{
return ExpressionTreeHelper<T>.True();
}
Expression<Func<T, bool>> initTree = ExpressionTreeHelper<T>.False();
foreach (PropertyInfo propertyInfo in Properties)
{
FullTextSearchIgnoreAttribute ignoreAttrbute = propertyInfo
.GetCustomAttributes()
.FirstOrDefault(attribute => attribute is FullTextSearchIgnoreAttribute)
as FullTextSearchIgnoreAttribute;
if (ignoreAttrbute == null)
{
//值类型
Type[] valueTypes = new Type[5] ;
//如果是可空类型
if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
valueTypes = new Type[5] { typeof(int?), typeof(byte?), typeof(double?), typeof(float?), typeof(DateTime?) };
Expression<Func<T, bool>> express = ExpressionTreeHelper<T>.CreateEqual(propertyInfo.Name, keyWords);
initTree = initTree.Or(express);
}
//值类型只能精准匹配
else if (valueTypes.Contains(propertyInfo.PropertyType))
{
valueTypes = new Type[5] { typeof(int), typeof(byte), typeof(double), typeof(float), typeof(DateTime) };
Expression<Func<T, bool>> express = ExpressionTreeHelper<T>.CreateEqual(propertyInfo.Name, keyWords);
initTree = initTree.Or(express);
}
else if(propertyInfo.PropertyType==typeof(string))
{
Expression<Func<T, bool>> express = ExpressionTreeHelper<T>.GetContains(propertyInfo.Name, keyWords);
initTree = initTree.Or(express);
}
}
}
return initTree;
}
}
}
@@ -0,0 +1,123 @@
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
namespace JSMachine.WMS.Infrastructure
{
public interface IGenericInterface
{
Type Type { get; }
Type[] GenericArguments { get; }
TDelegate GetMethod<TDelegate>(string methodName, params Type[] argTypes);
}
public static class GenericInterfaceExtensions
{
public static IGenericInterface AsGenericInterface(this object @this, Type type)
{
var interfaceType = (
from @interface in @this.GetType().GetInterfaces()
where @interface.IsGenericType
let definition = @interface.GetGenericTypeDefinition()
where definition == type
select @interface
)
.SingleOrDefault();
return interfaceType != null
? new GenericInterfaceImpl(@this, interfaceType)
: null;
}
private class GenericInterfaceImpl : IGenericInterface
{
private static readonly Regex ActionDelegateRegex = new Regex(@"^System\.Action(`\d{1,2})?", RegexOptions.Compiled);
private static readonly Regex FuncDelegateRegex = new Regex(@"^System\.Func`(\d{1,2})", RegexOptions.Compiled);
private readonly object _instance;
public Type Type { get; }
public Type[] GenericArguments => Type.GetGenericArguments();
public GenericInterfaceImpl(object instance, Type interfaceType)
{
_instance = instance;
Type = interfaceType;
}
public TDelegate GetMethod<TDelegate>(string methodName, params Type[] argTypes)
{
switch (GetDelegateType<TDelegate>())
{
case DelegateType.Action:
return GetAction<TDelegate>(methodName);
case DelegateType.ActionWithParams:
return GetActionWithParams<TDelegate>(methodName, argTypes);
default:
throw new NotSupportedException();
}
}
private TDelegate GetActionWithParams<TDelegate>(string methodName, params Type[] argTypes)
{
var methodInfo = Type.GetMethod(methodName) ?? throw new ArgumentException(nameof(methodName));
var argTypeList = argTypes.Any() ? argTypes : typeof(TDelegate).GetGenericArguments();
(ParameterExpression expression, Type type)[] argObjectParameters = argTypeList
.Select(item => (Expression.Parameter(typeof(object)), item))
.ToArray();
var method = Expression.Lambda<TDelegate>(
Expression.Call(
Expression.Constant(_instance),
methodInfo,
argObjectParameters.Select(item => Expression.Convert(item.expression, item.type))),
argObjectParameters.Select(item => item.expression))
.Compile();
return method;
}
private TDelegate GetAction<TDelegate>(string methodName)
{
var methodInfo = Type.GetMethod(methodName) ?? throw new ArgumentException(nameof(methodName));
var method = Expression.Lambda<TDelegate>(
Expression.Call(
Expression.Constant(_instance),
methodInfo))
.Compile();
return method;
}
private static DelegateType GetDelegateType<TDelegate>()
{
var actionMatch = ActionDelegateRegex.Match(typeof(TDelegate).FullName ?? throw new InvalidOperationException());
if (actionMatch.Success)
{
return actionMatch.Groups.Count > 1 ? DelegateType.ActionWithParams : DelegateType.Action;
}
var funcMatch = FuncDelegateRegex.Match(typeof(TDelegate).FullName ?? throw new InvalidOperationException());
if (funcMatch.Success)
{
return int.Parse(actionMatch.Groups[1].Value) > 1 ? DelegateType.FuncWithParams : DelegateType.Func;
}
return DelegateType.NotSupported;
}
private enum DelegateType
{
NotSupported,
Action,
Func,
ActionWithParams,
FuncWithParams
}
}
}
}
@@ -0,0 +1,36 @@
using JSMachine.WMS.Infrastructure.AppConfiguration;
using JSMachine.WMS.Infrastructure.Helper;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
namespace JSMachine.WMS.Common
{
public static class Global
{
public static AppSettings AppSettings { get; set; } = new AppSettings();
static Global()
{
string filePath = $@"{AppDomain.CurrentDomain.BaseDirectory}\appSettingsWebhost.json";
if (File.Exists(filePath))
{
string json = File.ReadAllText(filePath);
if (!string.IsNullOrEmpty(json))
{
JObject jobject = JObject.Parse(json);
string appSettings = jobject["AppSettings"].ToString();
AppSettings = JsonConvert.DeserializeObject<AppSettings>(appSettings);
return;
}
}
LogHelper.Error("配置文件读取错误!");
}
}
}
@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace JSMachine.DCS.Infrastructure
{
/// <summary>
/// 基础参数守卫工具,在进入业务流程前校验空值、路径和条件状态。
/// </summary>
public static class Guards
{
/// <summary>当任意参数为空时抛出参数异常。</summary>
/// <param name="parameters">待检查的参数集合。</param>
public static void ThrowIfNull(params object[] parameters)
{
if (parameters.Any(item => item == null))
throw new ArgumentNullException();
}
/// <summary>当任意字符串为空或空字符串时抛出参数异常。</summary>
/// <param name="strings">待检查的字符串集合。</param>
public static void ThrowIfNullOrEmpty(params string[] strings)
{
if (strings.Any(string.IsNullOrEmpty))
throw new ArgumentNullException();
}
/// <summary>检查字符串序列及其中的每一项是否为空。</summary>
/// <param name="strings">待检查的字符串序列。</param>
public static void ThrowIfNullOrEmpty(IEnumerable<string> strings)
{
ThrowIfNull(strings);
ThrowIfNullOrEmpty(strings.ToArray());
}
/// <summary>当指定文件不存在时抛出文件未找到异常。</summary>
/// <param name="path">文件路径。</param>
public static void ThrowIfFileNotFound(string path)
{
if (!File.Exists(path))
throw new FileNotFoundException("Can not found the specified file path. ", path);
}
/// <summary>当指定目录不存在时抛出目录未找到异常。</summary>
/// <param name="path">目录路径。</param>
public static void ThrowIfFolderNotFount(string path)
{
if (!Directory.Exists(path))
throw new DirectoryNotFoundException($"Can not found the specified path {path}. ");
}
/// <summary>当路径既不是文件也不是目录时抛出目录异常。</summary>
/// <param name="path">待检查的路径。</param>
public static void ThrowIfInvalidPath(string path)
{
if (!File.Exists(path) && !Directory.Exists(path))
throw new DirectoryNotFoundException($"The specified path is not a valid file or directory. ({path})");
}
/// <summary>当条件不成立时抛出无效操作异常。</summary>
/// <param name="condition">必须成立的条件。</param>
public static void ThrowIfNot(bool condition)
{
if (!condition)
throw new InvalidOperationException();
}
/// <summary>计算条件并在结果不成立时抛出无效操作异常。</summary>
/// <param name="condition">返回校验结果的委托。</param>
public static void ThrowIfNot(Func<bool> condition)
{
ThrowIfNull(condition);
ThrowIfNot(condition());
}
}
}
@@ -0,0 +1,387 @@
using JSMachine.DCS.Infrastructure;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using RestSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace JSMachine.WMS.Infrastructure.Helper
{
public static class HttpRequestHelper
{
/// <summary>
/// 字典方式请求,支持表单数据
/// </summary>
/// <param name="url"></param>
/// <param name="method"></param>
/// <param name="dic"></param>
/// <param name="postFileParam"></param>
/// <param name="timeOut"></param>
/// <returns></returns>
public async static Task<string> RequestByDic(string url,
Method method,
Dictionary<string, object> dic = null,
List<PostFileParam> postFileParam = null,
int timeOut = 5000)
{
RestClient client = new(url)
{
Timeout = timeOut
};
RestRequest request = new(method);
dic?.Select(p => p.Key)
.ToList()
.ForEach(key => request.AddParameter(key, dic[key]));
postFileParam?.ForEach(p =>
{
request.AddFile(p.RemoteParamName, p.FileBytes, p.FileName);
});
IRestResponse response = await client.ExecuteAsync(request);
if (response.StatusCode == HttpStatusCode.OK && response.ErrorException == null)
return response.Content;
if (response.ErrorException != null)
{
LogHelper.Error($"HttpRequstHandling.PostFile--{response.ErrorException.Message}");
LogHelper.Error("当前请求url:" + url);
}
return null;
}
/// <summary>
/// JSON参数请求
/// </summary>
/// <param name="url"></param>
/// <param name="method"></param>
/// <param name="json"></param>
/// <param name="timeOut"></param>
/// <returns></returns>
public async static Task<string> RequestByJson(string url, Method method, string json, int timeOut = 5000)
{
RestClient client = new(url)
{
Timeout = timeOut
};
RestRequest request = new(method);
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", json, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
if (response.StatusCode == HttpStatusCode.OK && response.ErrorException == null)
return response.Content;
if (response.ErrorException != null)
{
LogHelper.Error($"HttpRequstHandling.PostFile--{response.ErrorException.Message}");
LogHelper.Error("当前请求url:" + url);
}
return null;
}
/// <summary>
/// JSON参数请求
/// </summary>
/// <param name="url"></param>
/// <param name="method"></param>
/// <param name="json"></param>
/// <param name="token"></param>
/// <param name="timeOut"></param>
/// <returns></returns>
public async static Task<string> RequestByJson(string url, Method method, string json, string token, int timeOut = 5000)
{
RestClient client = new(url)
{
Timeout = timeOut
};
RestRequest request = new(method);
request.AddHeader("Authorization", $"Bearer {token}");
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", json, ParameterType.RequestBody);
IRestResponse response = await client.ExecuteAsync(request);
if (response.StatusCode == HttpStatusCode.OK && response.ErrorException == null)
return response.Content;
if (response.ErrorException != null)
{
LogHelper.Error($"HttpRequstHandling.PostFile--{response.ErrorException.Message}");
LogHelper.Error("当前请求url:" + url);
}
return null;
}
/// <summary>
/// 无参请求返回二进制(用于下载文件)
/// </summary>
/// <param name="url"></param>
/// <param name="method"></param>
/// <param name="timeOut"></param>
/// <returns></returns>
public async static Task<byte[]> RequestRturnRawAsync(string url, Method method, int timeOut = 5000)
{
if (string.IsNullOrEmpty(url))
return null;
RestClient client = new(url)
{
Timeout = timeOut
};
RestRequest request = new(method);
request.AlwaysMultipartFormData = true;
IRestResponse response = await client.ExecuteAsync(request);
if (response.StatusCode == HttpStatusCode.OK && response.ErrorException == null)
return response.RawBytes;
if (response.ErrorException != null)
{
LogHelper.Error($"HttpRequstHandling.PostFile--{response.ErrorException.Message}");
LogHelper.Error("当前请求url:" + url);
}
return null;
}
/// <summary>
/// 无参请求返回二进制(用于下载文件)
/// </summary>
/// <param name="url"></param>
/// <param name="method"></param>
/// <param name="timeOut"></param>
/// <returns></returns>
public static byte[] RequestRturnRaw(string url, Method method, int timeOut = 5000)
{
if (string.IsNullOrEmpty(url))
return null;
RestClient client = new(url)
{
Timeout = timeOut
};
RestRequest request = new(method);
request.AlwaysMultipartFormData = true;
IRestResponse response = client.Execute(request);
if (response.StatusCode == HttpStatusCode.OK && response.ErrorException == null)
return response.RawBytes;
if (response.ErrorException != null)
{
LogHelper.Error($"HttpRequstHandling.PostFile--{response.ErrorException.Message}");
LogHelper.Error("当前请求url:" + url);
}
return null;
}
/// <summary>
/// 获取请求的数据
/// </summary>
private static string GetResponseString(WebResponse webResponse)
{
using (var stream = webResponse.GetResponseStream())
{
if (stream == null) return string.Empty;
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}
/// <summary>
/// 以GET方式请求HTTP地址并获取返回
/// </summary>
public async static Task<string> Get(string url, Dictionary<string, string> headers = null,
CookieCollection cookies = null)
{
HttpWebRequest request = null;
WebResponse response = null;
try
{
ServicePointManager.DefaultConnectionLimit = 200;
if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
{
//对服务端证书进行有效性校验
ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;
}
request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
if (headers != null && headers.Count > 0)
{
foreach (var header in headers)
{
request.Headers.Add(header.Key, header.Value);
}
}
if (cookies != null)
{
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(cookies);
}
response = request.GetResponse();
return GetResponseString(response);
}
catch (System.Threading.ThreadAbortException e)
{
System.Threading.Thread.ResetAbort();
throw new Exception(e.Message);
}
finally
{
request?.Abort();
response?.Dispose();
}
}
/// <summary>
/// 以POST方式请求HTTP地址并获取返回
/// </summary>
/// <param name="url">HTTP地址</param>
/// <param name="parameters">POST的键值对参数</param>
/// <param name="headers"></param>
/// <param name="cookies"></param>
/// <returns></returns>
public async static Task<string> Post(string url, Dictionary<string, string> parameters,
Dictionary<string, string> headers = null, CookieCollection cookies = null)
{
return await Post(url, GetPostData(parameters), null, headers, cookies);
}
/// <summary>
/// 以POST方式请求HTTP地址并获取返回
/// </summary>
/// <param name="url">HTTP地址</param>
/// <param name="content">POST的内容</param>
/// <param name="contentType"></param>
/// <param name="headers"></param>
/// <param name="cookies"></param>
/// <returns></returns>
public async static Task<string> Post(string url, string content, string contentType = null,
Dictionary<string, string> headers = null, CookieCollection cookies = null)
{
HttpWebRequest request = null;
HttpWebResponse response = null;
try
{
ServicePointManager.DefaultConnectionLimit = 200;
//如果是发送HTTPS请求
if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
{
//对服务端证书进行有效性校验
ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;
}
request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.Timeout = 30000;
request.ContentType = contentType ?? "application/x-www-form-urlencoded";
if (headers != null && headers.Count > 0)
{
foreach (var header in headers)
{
request.Headers.Add(header.Key, header.Value);
}
}
if (cookies != null)
{
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(cookies);
}
//发送POST数据
var data = Encoding.UTF8.GetBytes(content ?? string.Empty);
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
response = (HttpWebResponse)request.GetResponse();
return GetResponseString(response);
}
catch (System.Threading.ThreadAbortException e)
{
System.Threading.Thread.ResetAbort();
throw new Exception(e.Message);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
finally
{
request?.Abort();
response?.Dispose();
}
}
/// <summary>
/// 字典转化为post数据
/// </summary>
/// <param name="dictionary"></param>
/// <returns></returns>
private static string GetPostData(Dictionary<string, string> dictionary)
{
if (dictionary == null || dictionary.Count == 0) return string.Empty;
var sb = new StringBuilder();
var keys = dictionary.Keys.ToList();
for (var i = 0; i < keys.Count; i++)
{
if (i > 0)
{
sb.Append("&");
}
sb.AppendFormat("{0}={1}", keys[i], HttpUtility.UrlEncode(dictionary[keys[i]]));
}
return sb.ToString();
}
/// <summary>
/// 验证证书
/// </summary>
private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain,
SslPolicyErrors errors)
{
return true;
}
}
public class PostFileParam
{
public string RemoteParamName { get; set; }
public string FileName { get; set; }
public byte[] FileBytes { get; set; }
}
}
@@ -0,0 +1,121 @@
using NLog;
using NLog.Web;
using System;
namespace JSMachine.WMS.Infrastructure.Helper
{
public static class LogHelper
{
private static ILogger logger = GetLogger();
private static ILogger GetLogger()
{
ILogger logger = NLogBuilder.ConfigureNLog("NLog.config").GetCurrentClassLogger();
return logger;
}
/// <summary>
/// 调试
/// </summary>
/// <param name="debug"></param>
public static void Debug(string debug)
{
logger.Debug(debug);
}
public static void Debug(Exception ex)
{
logger.Debug(ex);
}
public static void Debug(string debug,Exception ex)
{
logger.Debug(ex,debug);
}
/// <summary>
/// 信息
/// </summary>
/// <param name="info"></param>
public static void Info(string info)
{
logger.Info(info);
}
public static void Info(Exception ex)
{
logger.Info(ex);
}
public static void Info(string info,Exception ex)
{
logger.Info(ex,info);
}
/// <summary>
/// 警告
/// </summary>
/// <param name="warn"></param>
public static void Warn(string warn)
{
logger.Warn(warn);
}
public static void Warn(Exception ex)
{
logger.Warn(ex);
}
public static void Warn(string warn,Exception ex)
{
logger.Warn(ex,warn);
}
/// <summary>
/// 错误
/// </summary>
/// <param name="error"></param>
public static void Error(string error)
{
logger.Error(error);
}
public static void Error(Exception error)
{
logger.Error(error);
}
public static void Error(string error, Exception ex)
{
logger.Error(ex, error);
}
/// <summary>
/// 严重错误
/// </summary>
/// <param name="fatale"></param>
public static void Fatal(string fatal)
{
logger.Fatal(fatal);
}
public static void Fatal(Exception ex)
{
logger.Fatal(ex);
}
public static void Fatal(string fatal,Exception ex)
{
logger.Fatal(ex,fatal);
}
/// <summary>
/// 跟踪
/// </summary>
/// <param name="trace"></param>
public static void Trace(string trace)
{
logger.Trace(trace);
}
public static void Trace(Exception ex)
{
logger.Trace(ex);
}
public static void Trace(string trace,Exception ex)
{
logger.Trace(ex,trace);
}
}
}
@@ -0,0 +1,61 @@
using Org.BouncyCastle.Crypto.Digests;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace JSMachine.WMS.Infrastructure.Helper
{
/// <summary>
/// Md5加密辅助类
/// </summary>
public static class Md5EncryptionHelper
{
/// <summary>
/// 16位MD5加密
/// </summary>
/// <param name="password"></param>
/// <returns></returns>
public static string MD5Encrypt16(string str)
{
MD5 md5 = MD5.Create();
string t2 = BitConverter.ToString(md5.ComputeHash(Encoding.Default.GetBytes(str)), 4, 8);
t2 = t2.Replace("-", "");
return t2;
}
/// <summary>
/// 32位MD5加密
/// </summary>
/// <param name="password"></param>
/// <param name="lower">是否小写输出</param>
/// <returns></returns>
public static string MD5Encrypt32(string str, bool lower)
{
string cl = str;
string pwd = string.Empty;
MD5 md5 = MD5.Create(); //实例化一个md5对像
// 加密后是一个字节类型的数组,这里要注意编码UTF8/Unicode等的选择 
byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl));
// 通过使用循环,将字节类型的数组转换为字符串,此字符串是常规字符格式化所得
for (int i = 0; i < s.Length; i++)
{
// 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母,如果使用大写(X)则格式后的字符是大写字符
pwd = lower ? pwd + s[i].ToString("x").PadLeft(2, '0') : pwd + s[i].ToString("X").PadLeft(2, '0');
}
return pwd;
}
public static string MD5Encrypt64(string str)
{
string cl = str;
//string pwd = "";
MD5 md5 = MD5.Create(); //实例化一个md5对像
// 加密后是一个字节类型的数组,这里要注意编码UTF8/Unicode等的选择 
byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl));
return Convert.ToBase64String(s);
}
}
}
@@ -0,0 +1,30 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JSMachine.WMS.Infrastructure.Helper
{
/// <summary>
/// 对象拷贝帮助类
/// </summary>
public static class ObjectCloneHelper
{
/// <summary>
/// 深拷贝
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public static T DeepClone<T>(T t) where T : class
{
if (t == null)
return null;
string json = JsonConvert.SerializeObject(t);
return JsonConvert.DeserializeObject<T>(json);
}
}
}
@@ -0,0 +1,73 @@
using JSMachine.DCS.Infrastructure;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JSMachine.WMS.Infrastructure.Helper
{
public static class ProcessHelper
{
//调用浏览器打开指定的网址
public static bool OpenBrowserUrl(string url)
{
try
{
//优先用IE,不行再尝试用谷歌
if (OpenIe(url))
return true;
// 64位注册表路径
string openKey = @"SOFTWARE\Wow6432Node\Google\Chrome";
if (IntPtr.Size == 4)
{
// 32位注册表路径
openKey = @"SOFTWARE\Google\Chrome";
}
RegistryKey appPath = Registry.LocalMachine.OpenSubKey(openKey);
// 谷歌浏览器就用谷歌打开,没找到就用系统默认的浏览器
// 谷歌卸载了,注册表还没有清空,程序会返回一个"系统找不到指定的文件。"的bug
if (appPath != null)
{
Process result = Process.Start("chrome.exe", url);
return result != null;
}
else
{
Process result = Process.Start("chrome.exe", url);
return result != null;
}
}
catch (Exception ex)
{
LogHelper.Error(ex.Message);
}
return false;
}
/// <summary>
/// 用IE打开浏览器
/// </summary>
/// <param name="url"></param>
public static bool OpenIe(string url)
{
Process process = new();
process.StartInfo.FileName = "iexplore.exe"; //IE浏览器,可以更换
process.StartInfo.Arguments = url;
try
{
process.Start();
return true;
}
catch (Exception ex)
{
LogHelper.Error($"使用IE打开网址错误:{ex.Message}");
}
return false;
}
}
}
@@ -0,0 +1,20 @@
using BeetleX.BNR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JSMachine.WMS.Infrastructure.Helper
{
/// <summary>
/// 序列号生成帮助类
/// </summary>
public static class SerialNumHelper
{
public async static Task<string> GenerateSerialNum()
{
return await BNRFactory.Default.Create("[CN:WH][D:yyyyMMdd][N:[D:yyyyMMdd]/000000]");
}
}
}
@@ -0,0 +1,104 @@
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using static System.Net.Mime.MediaTypeNames;
namespace SuperDogTest
{
/// <summary>
/// 超级狗辅助类
/// </summary>
public static class SuperDogHelper
{
/// <summary>
/// 加载dll
/// </summary>
/// <param name="DllName"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
public extern static IntPtr LoadLibrary(string DllName);
/// <summary>
/// 释放dll
/// </summary>
/// <param name="hModule"></param>
/// <returns></returns>
[DllImport("kernel32")]
public extern static bool FreeLibrary(IntPtr hModule);
/// <summary>
/// 获取dll中的方法句柄
/// </summary>
/// <param name="hModule"></param>
/// <param name="ProcName"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
public extern static IntPtr GetProcAddress(IntPtr hModule, string ProcName);
/// <summary>
/// 查找加密狗委托
/// </summary>
/// <param name="Count"></param>
/// <returns></returns>
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int VikeyFindType(ref int Count);
/// <summary>
/// 读取加密狗数据委托
/// </summary>
/// <param name="Index"></param>
/// <param name="Addr"></param>
/// <param name="Length"></param>
/// <param name="buffer"></param>
/// <returns></returns>
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int VikeyReadDataType(int Index, int Addr, int Length, StringBuilder buffer);
/// <summary>
/// 管理员登录加密狗委托
/// </summary>
/// <param name="Index"></param>
/// <param name="AdminPassword"></param>
/// <returns></returns>
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int VikeyAdminLoginType(int Index, string AdminPassword);
/// <summary>
/// 加密狗句柄
/// </summary>
private static IntPtr VikeyHandle;
/// <summary>
/// 查找加密狗
/// </summary>
public static VikeyFindType VikeyFind { get; private set; }
/// <summary>
/// 加密狗管理员登录
/// </summary>
public static VikeyAdminLoginType VikeyAdminLogin { get; private set; }
/// <summary>
/// 加密狗读取数据
/// </summary>
public static VikeyReadDataType VikeyReadData { get; private set; }
static SuperDogHelper()
{
if (IntPtr.Size == 4)
{
VikeyHandle = LoadLibrary("ViKey32.dll");
}
else if (IntPtr.Size == 8)
{
VikeyHandle = LoadLibrary("ViKey64.dll");
}
else
return;
VikeyFind = Marshal.GetDelegateForFunctionPointer<VikeyFindType>(GetProcAddress(VikeyHandle, "VikeyFind"));
VikeyAdminLogin = Marshal.GetDelegateForFunctionPointer<VikeyAdminLoginType>(GetProcAddress(VikeyHandle, "VikeyAdminLogin"));
VikeyReadData = Marshal.GetDelegateForFunctionPointer<VikeyReadDataType>(GetProcAddress(VikeyHandle, "VikeyReadData"));
}
}
}
@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JSMachine.WMS.Infrastructure.Helper
{
/// <summary>
/// 值转换服务类
/// </summary>
public static class ValueConvertHelper
{
/// <summary>
/// 将一个int32类型转换为一个ushort数组,高位在前面
/// </summary>
/// <returns></returns>
public static ushort[] IntToUshorts(int value)
{
string str = Convert.ToString(value, 2).PadLeft(32, '0');
string high = str.Substring(0, 16);
string low = str.Substring(16);
return new ushort[2] { Convert.ToUInt16(high, 2), Convert.ToUInt16(low, 2) };
}
public static short[] IntToShorts(int value)
{
string str = Convert.ToString(value, 2).PadLeft(32, '0');
string high = str.Substring(0, 16);
string low = str.Substring(16);
return new short[2] { Convert.ToInt16(high, 2), Convert.ToInt16(low, 2) };
}
/// <summary>
/// 将两个ushort转换为一个int,高位在前
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
public static int UshortsToInt(ushort[] values)
{
return values.First() << 16 | values.Last();
}
/// <summary>
/// 将两个short转换为一个int,高位在前
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
public static int ShortsToInt(short[] values)
{
return values.First() << 16 | values.Last();
}
/// <summary>
/// 调整值的后一位强制转换成无符号
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
public static int adjShortsToInt(short[] values)
{
ushort value = (ushort)(values.Last());
return values.First() << 16 | value;
}
}
}
@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace JSMachine.WMS.Infrastructure.Helper
{
public static class XmlHelper
{
public static T XmlToModel<T>(string xml) where T : class, new()
{
try
{
xml = Regex.Replace(xml, @"<\?xml*.*?>", "", RegexOptions.IgnoreCase);
XmlSerializer xmlSer = new(typeof(T));
using (StringReader xmlReader = new(xml))
{
return (T)xmlSer.Deserialize(xmlReader);
}
}
catch (Exception ex)
{
return null;
//throw new Exception("将XML字符串转换为实体异常", ex); ;
}
}
public static string ModelToXml<T>(T obj) where T : class, new()
{
try
{
MemoryStream stream = new();
XmlSerializer xmlSer = new(typeof(T));
xmlSer.Serialize(stream, obj);
stream.Position = 0;
StreamReader sr = new(stream);
return sr.ReadToEnd();
}
catch (Exception ex)
{
return null;
//throw new Exception("将实体对象转换成XML异常", ex);
}
}
}
}
@@ -0,0 +1,68 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AssemblyTitle>Accelerider.Windows.Infrastructure</AssemblyTitle>
<Product>Accelerider.Windows.Infrastructure</Product>
<OutputPath>..\Build\$(Configuration)\</OutputPath>
<OutputType>Library</OutputType>
<PlatformTarget>x64</PlatformTarget>
<Platforms>AnyCPU;x64</Platforms>
<!--<UseWPF>true</UseWPF>-->
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebugType>pdbonly</DebugType>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Extensions\LoggerFacadeExtensions.cs" />
</ItemGroup>
<ItemGroup>
<None Remove="Accelerider.Windows.Infrastructure.csproj.DotSettings" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="11.0.1" />
<PackageReference Include="BeetleX.BNR" Version="1.0.1" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.5" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client.Core" Version="6.0.5" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="NLog" Version="5.0.1" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.0.0" />
<PackageReference Include="NPOI" Version="2.5.5" />
<PackageReference Include="Prism.Core" Version="8.1.97" />
<PackageReference Include="RestSharp" Version="106.15.0" />
<PackageReference Include="Rougamo.Fody" Version="1.4.1" />
<PackageReference Include="SqlSugarCore" Version="5.1.3.49" />
<PackageReference Include="System.Management" Version="6.0.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
<None Update="Logo.bmp">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="NLog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="ViKey32.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="ViKey64.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>false</ShowAllFiles>
</PropertyGroup>
</Project>
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace JSMachine.WMS.Infrastructure.Json
{
/// <summary>
/// Json基本设置
/// </summary>
public static class JsonSetting
{
public class DateTimeJsonConverter : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
if (DateTime.TryParse(reader.GetString(), out DateTime datetime))
{
return datetime;
}
}
return reader.GetDateTime();
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
}
}
/// <summary>
/// 公共Json序列化反序列化设置-忽略大小写,解决解决时间格式反序列化报错
/// </summary>
public static JsonSerializerOptions CommonJsonSerializerOptions = new()
{
PropertyNameCaseInsensitive = true
};
static JsonSetting()
{
CommonJsonSerializerOptions.Converters.Add(new DateTimeJsonConverter());
}
}
}
@@ -0,0 +1,79 @@
using System;
using System.Linq.Expressions;
namespace JSMachine.WMS.Infrastructure.LambdaHelp
{
public static class ExpressionExtension
{
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);
}
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>> AndAlso<T>(this Expression<Func<T, bool>> a, Expression<Func<T, bool>> b)
{
var p = Expression.Parameter(typeof(T), "p");
var bd = Expression.AndAlso(
Expression.Invoke(a, p),
Expression.Invoke(b, p));
var ld = Expression.Lambda<Func<T, bool>>(bd, p);
return ld;
}
//或拼接
public static Expression<Func<T, bool>> Orelse<T>(this Expression<Func<T, bool>> a, Expression<Func<T, bool>> b)
{
var p = Expression.Parameter(typeof(T), "p");
var bd = Expression.OrElse(
Expression.Invoke(a, p),
Expression.Invoke(b, p));
var ld = Expression.Lambda<Func<T, bool>>(bd, p);
return ld;
}
}
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,438 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Reflection;
namespace JSMachine.WMS.Infrastructure.LambdaHelp
{
public static class ExpressionTreeHelper<T>
{
/// <summary>
/// 创建lambda表达式:p=>p == null
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> Null(string propertyName)
{
return p => p.GetType().GetProperty(propertyName).GetValue(p) == null;
}
/// <summary>
/// 创建lambda表达式:p=>true
/// </summary>p != null
/// <typeparam name="T"></typeparam>
/// <returns></returns>zhangsansss
public static Expression<Func<T, bool>> NotNull(string propertyName)
{
return p => p.GetType().GetProperty(propertyName).GetValue(p) != null;
}
/// <summary>
/// 创建lambda表达式:p=>true
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> True()
{
return p => true;
}
/// <summary>
/// 创建lambda表达式:p=>false
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> False()
{
return p => false;
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <param name="sort"></param>
/// <returns></returns>
public static Expression<Func<T, TKey>> GetOrderExpression<TKey>(string propertyName)
{
ParameterExpression param = Expression.Parameter(typeof(T), "t");
return Expression.Lambda<Func<T, TKey>>
(
Expression.Convert(Expression.Property(param, propertyName),
typeof(object)),
param
);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName == propertyValue
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateEqual(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
Type type = typeof(T).GetProperty(propertyName).PropertyType;
if (!UnifyParamType(type, ref propertyValue))
{
return False();
}
////Type type = typeof(T).GetProperty(propertyName).PropertyType;
////propertyValue = propertyValue.ToString();
////propertyValue = Convert.ChangeType(propertyValue, type);
//ParameterExpression parameter = Expression.Parameter(typeof(T), "t");//创建参数p
//MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
//ConstantExpression constant = Expression.Constant(propertyValue);//创建常数
//return MyEqual(member, constant, parameter);
//propertyValue = propertyValue.ToString();
//propertyValue = Convert.ChangeType(propertyValue, type);
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue);//创建常数
//return Expression.Lambda<Func<T, bool>>(Expression.Equal(member, constant), parameter);
return MyEqual(member,constant,parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName != propertyValue
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="propertyName"></param>
/// <param name="propertyValue"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateNotEqual(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
Type type = typeof(T).GetProperty(propertyName).PropertyType;
propertyValue = Convert.ChangeType(propertyValue, type);
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue);//创建常数
return Expression.Lambda<Func<T, bool>>(Expression.NotEqual(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式: p=>propertyValue.Contains(p.propertyName) 目前仅支持 List<string>类型,后期完善
/// </summary>
/// <param name="propertyName"></param>
/// <param name="propertyValue"></param>
/// <returns></returns>
internal static Expression<Func<T, bool>> GetIn(string propertyName, object propertyValue)
{
//目前仅支持 List<string>类型,后期完善
try
{
//使用Newtonsoft的ToObject方法将JArray转换成List<string>类型
List<string> lst = ((dynamic)propertyValue).ToObject<List<string>>();
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(List<string>).GetMethod("Contains", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(lst, typeof(List<string>));
return Expression.Lambda<Func<T, bool>>(Expression.Call(constant, method, member), parameter);
}
catch (Exception ex)
{
throw new Exception("查询的参数不合法,无法解析成表达式目录树");
}
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName > propertyValue
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateGreaterThan(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
UnifyParamType(typeof(T).GetProperty(propertyName).PropertyType, ref propertyValue);
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue);//创建常数
return MyGreaterThan(member, constant, parameter);
//return Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName < propertyValue
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateLessThan(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
UnifyParamType(typeof(T).GetProperty(propertyName).PropertyType, ref propertyValue);
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue);//创建常数
return MyLessThan(member, constant, parameter);
//return Expression.Lambda<Func<T, bool>>(Expression.LessThan(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName >= propertyValue
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateGreaterThanOrEqual(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
UnifyParamType(typeof(T).GetProperty(propertyName).PropertyType, ref propertyValue);
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue);//创建常数
return MyGreaterThanOrEqual(member, constant, parameter);
//return Expression.Lambda<Func<T, bool>>(Expression.GreaterThanOrEqual(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName <= propertyValue
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateLessThanOrEqual(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
UnifyParamType(typeof(T).GetProperty(propertyName).PropertyType, ref propertyValue);
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue);//创建常数
return MyLessThanOrEqual(member, constant, parameter);
//return Expression.Lambda<Func<T, bool>>(Expression.LessThanOrEqual(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName.Contains(propertyValue)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> GetContains(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
Type type = typeof(T).GetProperty(propertyName).PropertyType;
if (!UnifyParamType(type, ref propertyValue))
{
return False();
}
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(propertyValue, typeof(string));
return Expression.Lambda<Func<T, bool>>(Expression.Call(member, method, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:!(p=>p.propertyName.Contains(propertyValue))
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> GetNotContains(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(propertyValue, typeof(string));
return Expression.Lambda<Func<T, bool>>(Expression.Not(Expression.Call(member, method, constant)), parameter);
}
/// <summary>
/// 创建lambda表达式:!(p=>p.propertyName.StartsWith(propertyValue))
/// </summary>
/// <param name="propertyName"></param>
/// <param name="propertyValue"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> GetStartsWith(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(propertyValue, typeof(string));
return Expression.Lambda<Func<T, bool>>(Expression.Not(Expression.Call(member, method, constant)), parameter);
}
/// <summary>
/// 创建lambda表达式:!(p=>p.propertyName.EndsWith(propertyValue))
/// </summary>
/// <param name="propertyName"></param>
/// <param name="propertyValue"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> GetEndsWith(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(propertyValue, typeof(string));
return Expression.Lambda<Func<T, bool>>(Expression.Not(Expression.Call(member, method, constant)), parameter);
}
/// <summary>
/// 统一参数类型(值大小比较方法中只支持int和DateTime类型,但上端传递过来的参数有可能为string类型,故需要使用反射的方式统一参数类型)
/// </summary>
/// <returns></returns>
private static bool UnifyParamType(Type type, ref object param)
{
//如果类型转换失败,说明无法转换,比如将字符串 aaa转换为 int类型等
try
{
if (IsNullableType(type))
{
NullableConverter nullableConverter = new(type);
param = nullableConverter.ConvertFromString(param.ToString());
}
else
{
//if (type != param.GetType())
param = Convert.ChangeType(param, type);
}
return true;
}
catch (Exception ex)
{
return false;
throw ex;
}
}
/// <summary>
/// 判断可空类型
/// </summary>
/// <param name="theType"></param>
/// <returns></returns>
private static bool IsNullableType(Type theType)
{
return (theType.IsGenericType && theType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)));
}
/// <summary>
/// 自定义小于比较
/// </summary>
/// <param name="e1"></param>
/// <param name="e2"></param>
/// <param name="parameter"></param>
/// <returns></returns>
private static Expression<Func<T, bool>> MyGreaterThan(Expression e1, Expression e2, ParameterExpression parameter)
{
if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
e2 = Expression.Convert(e2, e1.Type);
else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
e1 = Expression.Convert(e1, e2.Type);
return Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(e1, e2), parameter);
}
private static Expression<Func<T,bool>> MyEqual(Expression e1,Expression e2, ParameterExpression parameter)
{
if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
e2 = Expression.Convert(e2, e1.Type);
else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
e1 = Expression.Convert(e1, e2.Type);
return Expression.Lambda<Func<T, bool>>(Expression.Equal(e1, e2), parameter);
}
private static Expression<Func<T, bool>> MyContains(Expression e1, Expression e2, ParameterExpression parameter)
{
if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
e2 = Expression.Convert(e2, e1.Type);
else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
e1 = Expression.Convert(e1, e2.Type);
return Expression.Lambda<Func<T, bool>>(Expression.Equal(e1, e2), parameter);
}
/// <summary>
/// 自定义大于比较
/// </summary>
/// <param name="e1"></param>
/// <param name="e2"></param>
/// <param name="parameter"></param>
/// <returns></returns>
private static Expression<Func<T, bool>> MyLessThan(Expression e1, Expression e2, ParameterExpression parameter)
{
if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
e2 = Expression.Convert(e2, e1.Type);
else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
e1 = Expression.Convert(e1, e2.Type);
return Expression.Lambda<Func<T, bool>>(Expression.LessThan(e1, e2), parameter);
}
/// <summary>
/// 自定义大于等于比较
/// </summary>
/// <param name="e1"></param>
/// <param name="e2"></param>
/// <param name="parameter"></param>
/// <returns></returns>
private static Expression<Func<T, bool>> MyGreaterThanOrEqual(Expression e1, Expression e2, ParameterExpression parameter)
{
if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
e2 = Expression.Convert(e2, e1.Type);
else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
e1 = Expression.Convert(e1, e2.Type);
return Expression.Lambda<Func<T, bool>>(Expression.GreaterThanOrEqual(e1, e2), parameter);
}
/// <summary>
/// 自定义小于等于比较
/// </summary>
/// <param name="e1"></param>
/// <param name="e2"></param>
/// <param name="parameter"></param>
/// <returns></returns>
private static Expression<Func<T, bool>> MyLessThanOrEqual(Expression e1, Expression e2, ParameterExpression parameter)
{
if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
e2 = Expression.Convert(e2, e1.Type);
else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
e1 = Expression.Convert(e1, e2.Type);
return Expression.Lambda<Func<T, bool>>(Expression.LessThanOrEqual(e1, e2), parameter);
}
}
}
@@ -0,0 +1,45 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace JSMachine.WMS.Infrastructure.LambdaHelp
{
public class FilterCollection : Collection<IList<Filter>>
{
public FilterCollection() : base()
{ }
public FilterCollection(IList<IList<Filter>> lst) : base(lst)
{
}
}
public class Filter
{
public string PropertyName { get; set; }
public Op Operation { get; set; }
public object Value { get; set; }
}
public enum Op
{
NULL = 0,
NOTNUL = 1,
//查询List<string>类型的,当Count=0的时候选中(仅在MongoDB中有效)
Empty = 2,
//查询List<string>类型的,当Count>0的时候选中(仅在MongoDB中有效)
NotEmpty = 3,
Equals = 4,
NotEquals = 5,
GreaterThan = 6,
LessThan = 7,
GreaterThanOrEqual = 8,
LessThanOrEqual = 9,
Contains = 10,
NotContains = 11,
StartsWith = 12,
EndsWith = 13,
//包含查询,目前仅支持List<string>
In = 14
}
}
@@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace JSMachine.WMS.Infrastructure.LambdaHelp
{
public static class LambdaBuider<T>
{
public static Expression<Func<T, bool>> BuildExpreesion(FilterCollection filters)
{
Expression<Func<T, bool>> baseExpression = t => false;
if (filters == null || filters.Count == 0)
return t => true;
List<Expression<Func<T, bool>>> orExpressions = new List<Expression<Func<T, bool>>>();
for (int i = 0; i < filters.Count; i++)
{
for (int j = 0; j < filters[i].Count; j++)
{
string propName = filters[i][j].PropertyName;
object value = filters[i][j].Value;
switch (filters[i][j].Operation)
{
case Op.NULL:
{
if (typeof(T).GetProperty(propName).PropertyType == typeof(int) || typeof(T).GetProperty(propName) == typeof(long))
{
baseExpression = baseExpression.Or(LambdaHelper<T>.CreateEqual(propName, 0));
}
else
{
baseExpression = baseExpression.Or(LambdaHelper<T>.Null(propName));
}
}; break;
case Op.NOTNUL:
{
if (typeof(T).GetProperty(propName).PropertyType == typeof(int) || typeof(T).GetProperty(propName) == typeof(long))
{
baseExpression = baseExpression.Or(LambdaHelper<T>.CreateNotEqual(propName, 0));
}
else
{
baseExpression = baseExpression.Or(LambdaHelper<T>.NotNull(propName));
}
}; break;
case Op.Equals: baseExpression = baseExpression.Or(LambdaHelper<T>.CreateEqual(propName, value)); break;
case Op.NotEquals: baseExpression = baseExpression.Or(LambdaHelper<T>.CreateNotEqual(propName, value)); break;
case Op.GreaterThan: baseExpression = baseExpression.Or(LambdaHelper<T>.CreateGreaterThan(propName, value)); break;
case Op.LessThan: baseExpression = baseExpression.Or(LambdaHelper<T>.CreateLessThan(propName, value)); break;
case Op.GreaterThanOrEqual: baseExpression = baseExpression.Or(LambdaHelper<T>.CreateGreaterThanOrEqual(propName, value)); break;
case Op.LessThanOrEqual: baseExpression = baseExpression.Or(LambdaHelper<T>.CreateLessThanOrEqual(propName, value)); break;
case Op.Contains: baseExpression = baseExpression.Or(LambdaHelper<T>.GetContains(propName, value)); break;
case Op.NotContains: baseExpression = baseExpression.Or(LambdaHelper<T>.GetNotContains(propName, value)); break;
case Op.StartsWith: baseExpression = baseExpression.Or(LambdaHelper<T>.GetStartsWith(propName, value)); break;
case Op.EndsWith: baseExpression = baseExpression.Or(LambdaHelper<T>.GetEndsWith(propName, value)); break;
case Op.In: baseExpression = baseExpression.Or(LambdaHelper<T>.GetIn(propName, value)); break;
}
}
orExpressions.Add(baseExpression);
baseExpression = p => false;
}
Expression<Func<T, bool>> resultExpression = p => true;
orExpressions.ForEach(x =>
{
resultExpression = resultExpression.And(x);
});
return resultExpression;
}
}
}
@@ -0,0 +1,388 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Reflection;
namespace JSMachine.WMS.Infrastructure.LambdaHelp
{
public static class LambdaHelper<T>
{
/// <summary>
/// 创建lambda表达式:p=>p == null
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> Null(string propertyName)
{
return p => p.GetType().GetProperty(propertyName).GetValue(p) == null;
}
/// <summary>
/// 创建lambda表达式:p=>true
/// </summary>p != null
/// <typeparam name="T"></typeparam>
/// <returns></returns>zhangsansss
public static Expression<Func<T, bool>> NotNull(string propertyName)
{
return p => p.GetType().GetProperty(propertyName).GetValue(p) != null;
}
/// <summary>
/// 创建lambda表达式:p=>true
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> True()
{
return p => true;
}
/// <summary>
/// 创建lambda表达式:p=>false
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Expression<Func<T, bool>> False()
{
return p => false;
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <param name="sort"></param>
/// <returns></returns>
public static Expression<Func<T, TKey>> GetOrderExpression<TKey>(string propertyName)
{
ParameterExpression param = Expression.Parameter(typeof(T), "t");
//MemberExpression body = Expression.Property(param, propertyName);
//return Expression.Lambda<Func<T, TKey>>(Expression.Convert(body, typeof(T).GetProperty(propertyName).PropertyType));
return
Expression.Lambda<Func<T, TKey>>(
Expression.Convert(
Expression.Property(param, propertyName),
typeof(object)),
param);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName == propertyValue
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateEqual(string propertyName, object propertyValue)
{
var type = typeof(T).GetProperty(propertyName).PropertyType;
propertyValue = propertyValue.ToString();
propertyValue = Convert.ChangeType(propertyValue, type);
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue);//创建常数
return Expression.Lambda<Func<T, bool>>(Expression.Equal(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName != propertyValue
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="propertyName"></param>
/// <param name="propertyValue"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateNotEqual(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
var type = typeof(T).GetProperty(propertyName).PropertyType;
propertyValue = Convert.ChangeType(propertyValue, type);
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue);//创建常数
return Expression.Lambda<Func<T, bool>>(Expression.NotEqual(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式: p=>propertyValue.Contains(p.propertyName) 目前仅支持 List<string>类型,后期完善
/// </summary>
/// <param name="propertyName"></param>
/// <param name="propertyValue"></param>
/// <returns></returns>
internal static Expression<Func<T, bool>> GetIn(string propertyName, object propertyValue)
{
//目前仅支持 List<string>类型,后期完善
try
{
//使用Newtonsoft的ToObject方法将JArray转换成List<string>类型
List<string> lst = ((dynamic)propertyValue).ToObject<List<string>>();
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(List<string>).GetMethod("Contains", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(lst, typeof(List<string>));
return Expression.Lambda<Func<T, bool>>(Expression.Call(constant, method, member), parameter);
}
catch (Exception ex)
{
throw new Exception("查询的参数不合法,无法解析成表达式目录树");
}
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName > propertyValue
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateGreaterThan(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
UnifyParamType(typeof(T).GetProperty(propertyName).PropertyType, ref propertyValue);
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue);//创建常数
return MyGreaterThan(member, constant, parameter);
//return Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName < propertyValue
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateLessThan(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
UnifyParamType(typeof(T).GetProperty(propertyName).PropertyType, ref propertyValue);
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue);//创建常数
return MyLessThan(member, constant, parameter);
//return Expression.Lambda<Func<T, bool>>(Expression.LessThan(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName >= propertyValue
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateGreaterThanOrEqual(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
UnifyParamType(typeof(T).GetProperty(propertyName).PropertyType, ref propertyValue);
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue);//创建常数
return MyGreaterThanOrEqual(member, constant, parameter);
//return Expression.Lambda<Func<T, bool>>(Expression.GreaterThanOrEqual(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName <= propertyValue
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> CreateLessThanOrEqual(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
UnifyParamType(typeof(T).GetProperty(propertyName).PropertyType, ref propertyValue);
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");//创建参数p
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
ConstantExpression constant = Expression.Constant(propertyValue);//创建常数
return MyLessThanOrEqual(member, constant, parameter);
//return Expression.Lambda<Func<T, bool>>(Expression.LessThanOrEqual(member, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:p=>p.propertyName.Contains(propertyValue)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> GetContains(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(propertyValue, typeof(string));
return Expression.Lambda<Func<T, bool>>(Expression.Call(member, method, constant), parameter);
}
/// <summary>
/// 创建lambda表达式:!(p=>p.propertyName.Contains(propertyValue))
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="column"></param>
/// <param name="value"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> GetNotContains(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(propertyValue, typeof(string));
return Expression.Lambda<Func<T, bool>>(Expression.Not(Expression.Call(member, method, constant)), parameter);
}
/// <summary>
/// 创建lambda表达式:!(p=>p.propertyName.StartsWith(propertyValue))
/// </summary>
/// <param name="propertyName"></param>
/// <param name="propertyValue"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> GetStartsWith(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(propertyValue, typeof(string));
return Expression.Lambda<Func<T, bool>>(Expression.Not(Expression.Call(member, method, constant)), parameter);
}
/// <summary>
/// 创建lambda表达式:!(p=>p.propertyName.EndsWith(propertyValue))
/// </summary>
/// <param name="propertyName"></param>
/// <param name="propertyValue"></param>
/// <returns></returns>
public static Expression<Func<T, bool>> GetEndsWith(string propertyName, object propertyValue)
{
propertyValue = propertyValue.ToString();
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
MemberExpression member = Expression.PropertyOrField(parameter, propertyName);
MethodInfo method = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
ConstantExpression constant = Expression.Constant(propertyValue, typeof(string));
return Expression.Lambda<Func<T, bool>>(Expression.Not(Expression.Call(member, method, constant)), parameter);
}
/// <summary>
/// 统一参数类型(值大小比较方法中只支持int和DateTime类型,但上端传递过来的参数有可能为string类型,故需要使用反射的方式统一参数类型)
/// </summary>
/// <returns></returns>
private static void UnifyParamType(Type type, ref object param)
{
//param = type.GetMethod("Parse", new Type[] { typeof(string) }).Invoke(param, new object[] { param.ToString() });
if (IsNullableType(type))
{
NullableConverter nullableConverter = new(type);
param = nullableConverter.ConvertFromString(param.ToString());
}
else
{
param = Convert.ChangeType(param, type);
}
}
/// <summary>
/// 判断可空类型
/// </summary>
/// <param name="theType"></param>
/// <returns></returns>
private static bool IsNullableType(Type theType)
{
return (theType.IsGenericType && theType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)));
}
/// <summary>
/// 自定义小于比较
/// </summary>
/// <param name="e1"></param>
/// <param name="e2"></param>
/// <param name="parameter"></param>
/// <returns></returns>
private static Expression<Func<T, bool>> MyGreaterThan(Expression e1, Expression e2, ParameterExpression parameter)
{
if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
e2 = Expression.Convert(e2, e1.Type);
else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
e1 = Expression.Convert(e1, e2.Type);
return Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(e1, e2), parameter);
}
/// <summary>
/// 自定义大于比较
/// </summary>
/// <param name="e1"></param>
/// <param name="e2"></param>
/// <param name="parameter"></param>
/// <returns></returns>
private static Expression<Func<T, bool>> MyLessThan(Expression e1, Expression e2, ParameterExpression parameter)
{
if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
e2 = Expression.Convert(e2, e1.Type);
else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
e1 = Expression.Convert(e1, e2.Type);
return Expression.Lambda<Func<T, bool>>(Expression.LessThan(e1, e2), parameter);
}
/// <summary>
/// 自定义大于等于比较
/// </summary>
/// <param name="e1"></param>
/// <param name="e2"></param>
/// <param name="parameter"></param>
/// <returns></returns>
private static Expression<Func<T, bool>> MyGreaterThanOrEqual(Expression e1, Expression e2, ParameterExpression parameter)
{
if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
e2 = Expression.Convert(e2, e1.Type);
else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
e1 = Expression.Convert(e1, e2.Type);
return Expression.Lambda<Func<T, bool>>(Expression.GreaterThanOrEqual(e1, e2), parameter);
}
/// <summary>
/// 自定义小于等于比较
/// </summary>
/// <param name="e1"></param>
/// <param name="e2"></param>
/// <param name="parameter"></param>
/// <returns></returns>
private static Expression<Func<T, bool>> MyLessThanOrEqual(Expression e1, Expression e2, ParameterExpression parameter)
{
if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
e2 = Expression.Convert(e2, e1.Type);
else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
e1 = Expression.Convert(e1, e2.Type);
return Expression.Lambda<Func<T, bool>>(Expression.LessThanOrEqual(e1, e2), parameter);
}
}
}
@@ -0,0 +1,42 @@
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using SqlSugar;
namespace JSMachine.WMS.Infrastructure.LambdaHelp
{
public static class OrderExpression
{
public static ISugarQueryable<T> OrderByLambda<T>(this ISugarQueryable<T> source, string property, OrderByType orderByType)
{
return ApplyOrder<T>(source, property, orderByType.ToString());
}
static ISugarQueryable<T> ApplyOrder<T>(ISugarQueryable<T> source, string property, string methodName)
{
string[] props = property.Split('.');
Type type = typeof(T);
ParameterExpression arg = Expression.Parameter(type, "x");
Expression expr = arg;
foreach (string prop in props)
{
// use reflection (not ComponentModel) to mirror LINQ
PropertyInfo pi = type.GetProperty(prop);
expr = Expression.Property(expr, pi);
type = pi.PropertyType;
}
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);
object result = typeof(Queryable).GetMethods().Single(
method => method.Name == methodName
&& method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2
&& method.GetParameters().Length == 2)
.MakeGenericMethod(typeof(T), type)
.Invoke(null, new object[] { source, lambda });
return (ISugarQueryable<T>)result;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" throwExceptions="false" internalLogLevel="Warn" internalLogFile="${basedir}/logs/NlogRecords.log">
<!--指定了当NLog自己遇到Warn等级以上的报错时,生成日志到./logs/NlogRecords.log下(网站的相对路径)。除非纠错,不可以设为Trace否则速度很慢,起码Debug以上-->
<extensions>
<add assembly="NLog.Web.AspNetCore" />
</extensions>
<targets>
<!--通过数据库记录日志 配置
dbProvider请选择mysql或是sqlserver,同时注意连接字符串,需要安装对应的sql数据提供程序
dbProvider="MySql.Data.MySqlClient.MySqlConnection, MySql.Data" connectionString="server=192.168.137.10;database=EvMSDB;user=root;password=mysql@local"
dbProvider="Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient" connectionString="Server=192.168.1.204;Database=EvMSDB;User ID=sa;Password=yzhly@126"
-->
<!--<target name="log_database" xsi:type="Database" dbProvider="MySql.Data.MySqlClient.MySqlConnection, MySql.Data" connectionString="server=192.168.137.10;database=MSDB;user=root;password=mysql@local;">
<commandText>
INSERT INTO TblLogrecords (LogDate,LogLevel,Logger,Message,MachineName,MachineIp,NetRequestMethod,NetRequestUrl,NetUserIsauthenticated,NetUserAuthtype,NetUserIdentity,Exception)
VALUES(@LogDate,@LogLevel,@Logger,@Message,@MachineName,@MachineIp,@NetRequestMethod,@NetRequestUrl,@NetUserIsauthenticated,@NetUserAuthtype,@NetUserIdentity,@Exception);
</commandText>
<parameter name="@LogDate" layout="${date}" />
<parameter name="@LogLevel" layout="${level}" />
<parameter name="@Logger" layout="${logger}" />
<parameter name="@Message" layout="${message}" />
<parameter name="@MachineName" layout="${machinename}" />
<parameter name="@MachineIp" layout="${aspnet-request-ip}" />
<parameter name="@NetRequestMethod" layout="${aspnet-request-method}" />
<parameter name="@NetRequestUrl" layout="${aspnet-request-url}" />
<parameter name="@NetUserIsauthenticated" layout="${aspnet-user-isauthenticated}" />
<parameter name="@NetUserAuthtype" layout="${aspnet-user-authtype}" />
<parameter name="@NetUserIdentity" layout="${aspnet-user-identity}" />
<parameter name="@Exception" layout="${exception:tostring}" />
</target>-->
<!--输出文件-->
<target name="log_file" xsi:type="File" fileName="${basedir}/logs/${shortdate}.log" layout="${longdate} | ${level:uppercase=false} | ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}" />
<!--ColoredConsole彩色控制台 xsi:type="Console"是指定输出到普通控制台-->
<!--<target name="log_console" xsi:type="ColoredConsole" useDefaultRowHighlightingRules="true" layout="${longdate}|${level}|${logger}|${message} ${exception}">-->
<target name="log_console" xsi:type="ColoredConsole" useDefaultRowHighlightingRules="true" layout="${longdate}|${level}|${message} ${exception}">
<highlight-row condition="level == LogLevel.Trace" foregroundColor="DarkGray" />
<highlight-row condition="level == LogLevel.Debug" foregroundColor="Gray" />
<highlight-row condition="level == LogLevel.Info" foregroundColor="Green" />
<highlight-row condition="level == LogLevel.Warn" foregroundColor="Yellow" />
<highlight-row condition="level == LogLevel.Error" foregroundColor="Red" />
<highlight-row condition="level == LogLevel.Fatal" foregroundColor="Magenta" backgroundColor="White" />
</target>
</targets>
<rules>
<!--跳过所有级别的Microsoft组件的日志记录-->
<!--<logger name="Microsoft.*" maxlevel="Info" final="true" />-->
<!-- BlackHole without writeTo -->
<!--只通过数据库记录日志,这里的*,如果给了name名字,代码里用日志记录的时候,取logger需要把name当做参数-->
<!--<logger name="*" minlevel="Info" writeTo="log_database" />-->
<logger name="*" minlevel="Info" writeTo="log_console" />
<logger name="*" minlevel="Info" writeTo="log_file" />
<logger name="*" minlevel="Warn" writeTo="log_file" />
<logger name="*" minlevel="Error" writeTo="log_file" />
</rules>
</nlog>
@@ -0,0 +1,12 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("FB51D520-580D-42B0-AEF3-6C997918E9C3")]
[assembly: InternalsVisibleTo("JSMachine.DCS.InfrastructureTests")]
@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace JSMachine.DCS.Infrastructure.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JSMachine.DCS.Infrastructure.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
@@ -0,0 +1,16 @@
using System.Reflection;
[assembly: AssemblyCopyright("Copyright © J.S.Machine Team 2022")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("0.0.2.0")]
//[assembly: AssemblyFileVersion("0.0.2.0")]
@@ -0,0 +1,28 @@
namespace JSMachine.WMS.Infrastructure.Static
{
/// <summary>
/// 静态变量类
/// </summary>
public static class PaperReturnVariable
{
/// <summary>
/// 地磅称重重量
/// </summary>
public static float ResultWeight { get; set; } = 0;
/// <summary>
/// 地磅当前重量
/// </summary>
public static float CurrentWeight { get; set; } = 0;
/// <summary>
/// 是否可以读取
/// </summary>
public static bool CanRead { get; set; } = true;
/// <summary>
/// 条码
/// </summary>
public static string BarCode { get; set; }
}
}
@@ -0,0 +1,140 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Text.RegularExpressions;
using JSMachine.WMS.Infrastructure.Helper;
using Microsoft.Win32;
namespace JSMachine.DCS.Infrastructure
{
public static class SystemInfo
{
private const string ExtractionFailed = "<Extraction Failed>";
public static readonly string Caption;
public static readonly string CSName;
public static readonly string InstallDate;
public static readonly string OSArchitecture;
public static readonly string SerialNumber;
public static readonly string Version;
public static readonly long TotalVisibleMemorySize;
public static readonly string CPUName;
public static readonly DotNetFramework DotNetFrameworkVersion;
static SystemInfo()
{
var extractionRegex = new Regex("(\\w+?) ?= ?\"(.+?)\";", RegexOptions.Compiled | RegexOptions.Multiline);
var systemInfo = GetManagementInfo("SELECT * FROM Win32_OperatingSystem", extractionRegex);
var processorInfo = GetManagementInfo("SELECT * FROM Win32_Processor", extractionRegex);
Caption = systemInfo.GetValue("Caption");
CSName = systemInfo.GetValue("CSName");
InstallDate = systemInfo.GetValue("InstallDate");
OSArchitecture = systemInfo.GetValue("OSArchitecture");
SerialNumber = systemInfo.GetValue("SerialNumber");
Version = systemInfo.GetValue("Version");
TotalVisibleMemorySize = systemInfo.GetValue("TotalVisibleMemorySize").CastTo<long>();
CPUName = processorInfo.GetValue("Name");
DotNetFrameworkVersion = Get45PlusFromRegistry();
}
private static IReadOnlyDictionary<string, string> GetManagementInfo(string query, Regex regex)
{
try
{
var result = new ManagementObjectSearcher(new ObjectQuery(query));
var infoString = string.Empty;
using (var collection = result.Get())
{
foreach (var item in collection)
{
var managementObject = item as ManagementObject;
infoString = managementObject?.GetText(TextFormat.Mof);
if (!string.IsNullOrEmpty(infoString)) break;
}
}
if (string.IsNullOrEmpty(infoString)) return null;
return regex.Matches(infoString).OfType<Match>()
.Where(item => item.Success)
.ToDictionary(item => item.Groups[1].Value, item => item.Groups[2].Value);
}
catch (Exception e)
{
LogHelper.Error("An unexpected exception occured while getting management info. ", e);
return null;
}
}
private static string GetValue(this IReadOnlyDictionary<string, string> info, string key)
{
return info != null && info.TryGetValue(key, out var value) ? value : ExtractionFailed;
}
/*
* Refer to:
* Check Framework 45+: https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed#net_d;
*/
private static DotNetFramework Get45PlusFromRegistry()
{
const string subKey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
using (RegistryKey ndpKey = RegistryKey
.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)
.OpenSubKey(subKey))
{
return ndpKey?.GetValue("Release") != null
? CheckFor45PlusVersion((int)ndpKey.GetValue("Release"))
: DotNetFramework.Unknown;
}
}
// Checking the version using >= will enable forward compatibility.
private static DotNetFramework CheckFor45PlusVersion(int releaseKey)
{
if (releaseKey >= 461808)
return DotNetFramework.V472OrLater;
if (releaseKey >= 461308)
return DotNetFramework.V471;
if (releaseKey >= 460798)
return DotNetFramework.V47;
if (releaseKey >= 394802)
return DotNetFramework.V462;
if (releaseKey >= 394254)
return DotNetFramework.V461;
if (releaseKey >= 393295)
return DotNetFramework.V46;
if (releaseKey >= 379893)
return DotNetFramework.V452;
if (releaseKey >= 378675)
return DotNetFramework.V451;
if (releaseKey >= 378389)
return DotNetFramework.V45;
// This code should never execute. A non-null release key should mean
// that 4.5 or later is installed.
return DotNetFramework.V472OrLater;
}
}
public enum DotNetFramework
{
Unknown,
V45,
V451,
V452,
V46,
V461,
V462,
V47,
V471,
V472OrLater
}
}
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>