忽略dll文件git
This commit is contained in:
@@ -1,71 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
|
||||
namespace Hncore.Infrastructure.AliYun
|
||||
{
|
||||
public class AliDayu
|
||||
{
|
||||
const string SignName = "";
|
||||
private IHttpClientFactory _httpClientFactory;
|
||||
|
||||
public AliDayu(IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
public async Task<bool> SendSms(List<string> PhoneNumbers, string templateCode, object content)
|
||||
{
|
||||
Dictionary<string, string> paramDic = Util.BuildCommonParam();
|
||||
|
||||
paramDic.Add("Action", "SendSms");
|
||||
paramDic.Add("Version", "2017-05-25");
|
||||
paramDic.Add("RegionId", "cn-hangzhou");
|
||||
paramDic.Add("PhoneNumbers", ListHelper<string>.ListToStr(PhoneNumbers));
|
||||
paramDic.Add("SignName", SignName);
|
||||
paramDic.Add("TemplateCode", templateCode);
|
||||
paramDic.Add("TemplateParam", content.ToJson());
|
||||
|
||||
string sign = Util.CreateSign(paramDic);
|
||||
|
||||
paramDic.Add("Signature", sign);
|
||||
|
||||
var httpClient = _httpClientFactory.CreateClient("AliDayu");
|
||||
|
||||
string url = "http://dysmsapi.aliyuncs.com";
|
||||
|
||||
foreach (var keyValuePair in paramDic)
|
||||
{
|
||||
url = UrlHelper.SetUrlParam(keyValuePair.Key, keyValuePair.Value);
|
||||
}
|
||||
|
||||
var res = await httpClient.GetStringAsync(url);
|
||||
|
||||
SendSmsResponse result = XML.XmlDeserialize<SendSmsResponse>(res);
|
||||
|
||||
if (result.Code == "OK")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
LogHelper.Error("阿里大于短信发送失败", res);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[XmlRoot]
|
||||
public class SendSmsResponse
|
||||
{
|
||||
[XmlElement] public string Message { get; set; }
|
||||
|
||||
[XmlElement] public string RequestId { get; set; }
|
||||
|
||||
[XmlElement] public string BizId { get; set; }
|
||||
|
||||
[XmlElement] public string Code { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
|
||||
namespace Hncore.Infrastructure.AliYun
|
||||
{
|
||||
public class Util
|
||||
{
|
||||
const string QUERY_SEPARATOR = "&";
|
||||
const string HEADER_SEPARATOR = "\n";
|
||||
|
||||
const string AccessSecret = "r8FfRmoeWcCJyZSqqkQP2G3dKPPl2N ";
|
||||
private const string AccessKeyId = "LTAI4FmSkDSwFuXeLxsDB3jB";
|
||||
|
||||
public static string CreateSign(Dictionary<string, string> data, string method = "GET")
|
||||
{
|
||||
var dic = new RouteValueDictionary(data);
|
||||
|
||||
|
||||
string[] array = dic.OrderBy(a => a.Key, StringComparer.Ordinal)
|
||||
.Select(a => PercentEncode(a.Key) + "=" + PercentEncode(a.Value.ToString())).ToArray();
|
||||
string dataStr = string.Join("&", array);
|
||||
string signStr = method + "&" + PercentEncode("/") + "&" + PercentEncode(dataStr);
|
||||
|
||||
HMACSHA1 myhmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(AccessSecret + "&"));
|
||||
byte[] byteArray = Encoding.UTF8.GetBytes(signStr);
|
||||
MemoryStream stream = new MemoryStream(byteArray);
|
||||
string signature = Convert.ToBase64String(myhmacsha1.ComputeHash(stream));
|
||||
|
||||
return signature;
|
||||
}
|
||||
|
||||
private static string PercentEncode(string value)
|
||||
{
|
||||
return UpperCaseUrlEncode(value)
|
||||
.Replace("+", "%20")
|
||||
.Replace("*", "%2A")
|
||||
.Replace("%7E", "~");
|
||||
}
|
||||
|
||||
private static string UpperCaseUrlEncode(string s)
|
||||
{
|
||||
char[] temp = HttpUtility.UrlEncode(s).ToCharArray();
|
||||
for (int i = 0; i < temp.Length - 2; i++)
|
||||
{
|
||||
if (temp[i] == '%')
|
||||
{
|
||||
temp[i + 1] = char.ToUpper(temp[i + 1]);
|
||||
temp[i + 2] = char.ToUpper(temp[i + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
return new string(temp);
|
||||
}
|
||||
|
||||
public static IDictionary<string, string> SortDictionary(Dictionary<string, string> dic)
|
||||
{
|
||||
IDictionary<string, string> sortedDictionary =
|
||||
new SortedDictionary<string, string>(dic, StringComparer.Ordinal);
|
||||
return sortedDictionary;
|
||||
}
|
||||
|
||||
|
||||
public static Dictionary<string, string> BuildCommonParam()
|
||||
{
|
||||
Dictionary<string, string> dic = new Dictionary<string, string>();
|
||||
|
||||
dic.Add("AccessKeyId", AccessKeyId);
|
||||
dic.Add("Timestamp", DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"));
|
||||
dic.Add("SignatureMethod", "HMAC-SHA1");
|
||||
dic.Add("SignatureVersion", "1.0");
|
||||
dic.Add("SignatureNonce", Guid.NewGuid().ToString());
|
||||
|
||||
return dic;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
using Hncore.Infrastructure.IOC;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Hncore.Infrastructure.DDD;
|
||||
using Hncore.Infrastructure.EF;
|
||||
|
||||
namespace Hncore.Infrastructure.Autofac
|
||||
{
|
||||
public class MvcAutoRegister
|
||||
{
|
||||
public IServiceProvider Build(IServiceCollection services, IMvcBuilder mvcBuilder,
|
||||
Action<ContainerBuilder> action = null)
|
||||
{
|
||||
mvcBuilder.AddControllersAsServices();
|
||||
|
||||
var builder = new ContainerBuilder();
|
||||
|
||||
var assemblys = AppDomain.CurrentDomain.GetAssemblies().ToArray();
|
||||
|
||||
var perRequestType = typeof(IPerRequest);
|
||||
builder.RegisterAssemblyTypes(assemblys)
|
||||
.Where(t => perRequestType.IsAssignableFrom(t) && t != perRequestType)
|
||||
.PropertiesAutowired()
|
||||
.AsImplementedInterfaces()
|
||||
.InstancePerLifetimeScope();
|
||||
|
||||
var perDependencyType = typeof(IDependency);
|
||||
builder.RegisterAssemblyTypes(assemblys)
|
||||
.Where(t => perDependencyType.IsAssignableFrom(t) && t != perDependencyType)
|
||||
.PropertiesAutowired()
|
||||
.AsImplementedInterfaces()
|
||||
.InstancePerDependency();
|
||||
|
||||
var singleInstanceType = typeof(ISingleInstance);
|
||||
builder.RegisterAssemblyTypes(assemblys)
|
||||
.Where(t => singleInstanceType.IsAssignableFrom(t) && t != singleInstanceType)
|
||||
.PropertiesAutowired()
|
||||
.AsImplementedInterfaces()
|
||||
.SingleInstance();
|
||||
|
||||
builder.RegisterGeneric(typeof(QueryBase<,>)).As(typeof(IQuery<,>)).PropertiesAutowired()
|
||||
.InstancePerLifetimeScope();
|
||||
|
||||
builder.RegisterGeneric(typeof(RepositoryBase<,>)).As(typeof(IRepository<,>)).PropertiesAutowired()
|
||||
.InstancePerLifetimeScope();
|
||||
|
||||
action?.Invoke(builder);
|
||||
|
||||
builder.Populate(services);
|
||||
|
||||
var container = builder.Build();
|
||||
|
||||
var servicesProvider = new AutofacServiceProvider(container);
|
||||
|
||||
return servicesProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using System.Text;
|
||||
|
||||
namespace Hncore.Infrastructure.CSV
|
||||
{
|
||||
public class CsvRow
|
||||
{
|
||||
private string _content = "";
|
||||
|
||||
public CsvRow AddCell(string content)
|
||||
{
|
||||
if (_content != "")
|
||||
{
|
||||
_content += ",";
|
||||
}
|
||||
|
||||
_content += StringToCsvCell(content);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _content;
|
||||
}
|
||||
|
||||
private static string StringToCsvCell(string str)
|
||||
{
|
||||
bool mustQuote = str.Contains(",") || str.Contains("\"") || str.Contains("\r") || str.Contains("\n");
|
||||
if (mustQuote)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("\"");
|
||||
foreach (char nextChar in str)
|
||||
{
|
||||
sb.Append(nextChar);
|
||||
if (nextChar == '"')
|
||||
{
|
||||
sb.Append("\"");
|
||||
}
|
||||
}
|
||||
|
||||
sb.Append("\"");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Hncore.Infrastructure.CSV
|
||||
{
|
||||
public class CsvTemporaryFile : IDisposable
|
||||
{
|
||||
private string filePath = "";
|
||||
private FileStream _fileStream;
|
||||
private StreamWriter _streamWriter;
|
||||
|
||||
public CsvTemporaryFile()
|
||||
{
|
||||
var execDir = Path.GetDirectoryName(typeof(CsvTemporaryFile).Assembly.Location);
|
||||
|
||||
string tempDir = Path.Combine(execDir, "temp", DateTime.Now.ToString("yyyyMMdd"));
|
||||
|
||||
if (!Directory.Exists(tempDir))
|
||||
{
|
||||
Directory.CreateDirectory(tempDir);
|
||||
}
|
||||
|
||||
filePath = Path.Combine(tempDir, Guid.NewGuid().ToString());
|
||||
|
||||
_fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write);
|
||||
_streamWriter = new StreamWriter(_fileStream, Encoding.GetEncoding("GB2312"));
|
||||
_streamWriter.AutoFlush = true;
|
||||
}
|
||||
|
||||
public void WriteLine(CsvRow row)
|
||||
{
|
||||
_streamWriter.WriteLine(row.ToString());
|
||||
}
|
||||
|
||||
public async Task ResponseAsync(HttpResponse httpResponse, string fileName)
|
||||
{
|
||||
httpResponse.ContentType = "application/octet-stream";
|
||||
httpResponse.Headers.Add("Content-Disposition", $"attachment; filename={fileName.UrlEncode()}");
|
||||
httpResponse.Headers.Add("X-Suggested-Filename", fileName.UrlEncode());
|
||||
|
||||
using (FileStream fs = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
using (BufferedStream bs = new BufferedStream(fs))
|
||||
{
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
|
||||
long total_read = 0;
|
||||
DateTime begin = DateTime.Now;
|
||||
TimeSpan ts = new TimeSpan();
|
||||
|
||||
while ((bytesRead = bs.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
await httpResponse.Body.WriteAsync(buffer, 0, bytesRead);
|
||||
await httpResponse.Body.FlushAsync();
|
||||
|
||||
total_read += bytesRead;
|
||||
ts = DateTime.Now - begin;
|
||||
if (total_read / ts.TotalSeconds > 1024 * 1000)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_streamWriter?.Dispose();
|
||||
_fileStream?.Dispose();
|
||||
|
||||
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
File.Delete(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Globalization;
|
||||
|
||||
#if !SILVERLIGHT
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
#endif
|
||||
|
||||
namespace Hncore.Infrastructure.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Assembly Util Class
|
||||
/// </summary>
|
||||
public static class AssemblyUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates the instance from type name.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns></returns>
|
||||
public static T CreateInstance<T>(string type)
|
||||
{
|
||||
return CreateInstance<T>(type, new object[0]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the instance from type name and parameters.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns></returns>
|
||||
public static T CreateInstance<T>(string type, object[] parameters)
|
||||
{
|
||||
Type instanceType = null;
|
||||
var result = default(T);
|
||||
|
||||
instanceType = Type.GetType(type, true);
|
||||
|
||||
if (instanceType == null)
|
||||
throw new Exception(string.Format("The type '{0}' was not found!", type));
|
||||
|
||||
object instance = Activator.CreateInstance(instanceType, parameters);
|
||||
result = (T)instance;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type by the full name, also return matched generic type without checking generic type parameters in the name.
|
||||
/// </summary>
|
||||
/// <param name="fullTypeName">Full name of the type.</param>
|
||||
/// <param name="throwOnError">if set to <c>true</c> [throw on error].</param>
|
||||
/// <param name="ignoreCase">if set to <c>true</c> [ignore case].</param>
|
||||
/// <returns></returns>
|
||||
#if !NET35
|
||||
public static Type GetType(string fullTypeName, bool throwOnError, bool ignoreCase)
|
||||
{
|
||||
var targetType = Type.GetType(fullTypeName, false, ignoreCase);
|
||||
|
||||
if (targetType != null)
|
||||
return targetType;
|
||||
|
||||
var names = fullTypeName.Split(',');
|
||||
var assemblyName = names[1].Trim();
|
||||
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.Load(assemblyName);
|
||||
|
||||
var typeNamePrefix = names[0].Trim() + "`";
|
||||
|
||||
var matchedTypes = assembly.GetExportedTypes().Where(t => t.IsGenericType
|
||||
&& t.FullName.StartsWith(typeNamePrefix, ignoreCase, CultureInfo.InvariantCulture)).ToArray();
|
||||
|
||||
if (matchedTypes.Length != 1)
|
||||
return null;
|
||||
|
||||
return matchedTypes[0];
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (throwOnError)
|
||||
throw e;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
#else
|
||||
public static Type GetType(string fullTypeName, bool throwOnError, bool ignoreCase)
|
||||
{
|
||||
return Type.GetType(fullTypeName, null, (a, n, ign) =>
|
||||
{
|
||||
var targetType = a.GetType(n, false, ign);
|
||||
|
||||
if (targetType != null)
|
||||
return targetType;
|
||||
|
||||
var typeNamePrefix = n + "`";
|
||||
|
||||
var matchedTypes = a.GetExportedTypes().Where(t => t.IsGenericType
|
||||
&& t.FullName.StartsWith(typeNamePrefix, ign, CultureInfo.InvariantCulture)).ToArray();
|
||||
|
||||
if (matchedTypes.Length != 1)
|
||||
return null;
|
||||
|
||||
return matchedTypes[0];
|
||||
}, throwOnError, ignoreCase);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets the implement types from assembly.
|
||||
/// </summary>
|
||||
/// <typeparam name="TBaseType">The type of the base type.</typeparam>
|
||||
/// <param name="assembly">The assembly.</param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<Type> GetImplementTypes<TBaseType>(this Assembly assembly)
|
||||
{
|
||||
return assembly.GetExportedTypes().Where(t =>
|
||||
t.IsSubclassOf(typeof(TBaseType)) && t.IsClass && !t.IsAbstract);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the implemented objects by interface.
|
||||
/// </summary>
|
||||
/// <typeparam name="TBaseInterface">The type of the base interface.</typeparam>
|
||||
/// <param name="assembly">The assembly.</param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<TBaseInterface> GetImplementedObjectsByInterface<TBaseInterface>(this Assembly assembly)
|
||||
where TBaseInterface : class
|
||||
{
|
||||
return GetImplementedObjectsByInterface<TBaseInterface>(assembly, typeof(TBaseInterface));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the implemented objects by interface.
|
||||
/// </summary>
|
||||
/// <typeparam name="TBaseInterface">The type of the base interface.</typeparam>
|
||||
/// <param name="assembly">The assembly.</param>
|
||||
/// <param name="targetType">Type of the target.</param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<TBaseInterface> GetImplementedObjectsByInterface<TBaseInterface>(this Assembly assembly, Type targetType)
|
||||
where TBaseInterface : class
|
||||
{
|
||||
Type[] arrType = assembly.GetExportedTypes();
|
||||
|
||||
var result = new List<TBaseInterface>();
|
||||
|
||||
for (int i = 0; i < arrType.Length; i++)
|
||||
{
|
||||
var currentImplementType = arrType[i];
|
||||
|
||||
if (currentImplementType.IsAbstract)
|
||||
continue;
|
||||
|
||||
if (!targetType.IsAssignableFrom(currentImplementType))
|
||||
continue;
|
||||
|
||||
result.Add((TBaseInterface)Activator.CreateInstance(currentImplementType));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if SILVERLIGHT
|
||||
#else
|
||||
/// <summary>
|
||||
/// Clone object in binary format.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="target">The target.</param>
|
||||
/// <returns></returns>
|
||||
public static T BinaryClone<T>(this T target)
|
||||
{
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
formatter.Serialize(ms, target);
|
||||
ms.Position = 0;
|
||||
return (T)formatter.Deserialize(ms);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Copies the properties of one object to another object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="target">The target.</param>
|
||||
/// <returns></returns>
|
||||
public static T CopyPropertiesTo<T>(this T source, T target)
|
||||
{
|
||||
return source.CopyPropertiesTo(p => true, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the properties of one object to another object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="predict">The properties predict.</param>
|
||||
/// <param name="target">The target.</param>
|
||||
/// <returns></returns>
|
||||
public static T CopyPropertiesTo<T>(this T source, Predicate<PropertyInfo> predict, T target)
|
||||
{
|
||||
PropertyInfo[] properties = source.GetType()
|
||||
.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);
|
||||
|
||||
Dictionary<string, PropertyInfo> sourcePropertiesDict = properties.ToDictionary(p => p.Name);
|
||||
|
||||
PropertyInfo[] targetProperties = target.GetType()
|
||||
.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty)
|
||||
.Where(p => predict(p)).ToArray();
|
||||
|
||||
for (int i = 0; i < targetProperties.Length; i++)
|
||||
{
|
||||
var p = targetProperties[i];
|
||||
PropertyInfo sourceProperty;
|
||||
|
||||
if (sourcePropertiesDict.TryGetValue(p.Name, out sourceProperty))
|
||||
{
|
||||
if (sourceProperty.PropertyType != p.PropertyType)
|
||||
continue;
|
||||
|
||||
if (!sourceProperty.PropertyType.IsSerializable)
|
||||
continue;
|
||||
|
||||
p.SetValue(target, sourceProperty.GetValue(source, null), null);
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assemblies from string.
|
||||
/// </summary>
|
||||
/// <param name="assemblyDef">The assembly def.</param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<Assembly> GetAssembliesFromString(string assemblyDef)
|
||||
{
|
||||
return GetAssembliesFromStrings(assemblyDef.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assemblies from strings.
|
||||
/// </summary>
|
||||
/// <param name="assemblies">The assemblies.</param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<Assembly> GetAssembliesFromStrings(string[] assemblies)
|
||||
{
|
||||
List<Assembly> result = new List<Assembly>(assemblies.Length);
|
||||
|
||||
foreach (var a in assemblies)
|
||||
{
|
||||
result.Add(Assembly.Load(a));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool IsImplementedInterface<T, TInterface>()
|
||||
{
|
||||
return typeof(TInterface).IsAssignableFrom(typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// 二进制序列化
|
||||
/// </summary>
|
||||
public class BinaryHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 序列化对象(二进制)
|
||||
/// </summary>
|
||||
/// <param name="obj">需要序列化的对象</param>
|
||||
public static byte[] Serialize(object obj)
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
BinaryFormatter binaryFormatter = new BinaryFormatter();
|
||||
binaryFormatter.Serialize(ms, obj);
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化对象(二进制)
|
||||
/// </summary>
|
||||
/// <param name="bytes">需要反序列化的字符串</param>
|
||||
public static object Deserialize(byte[] bytes)
|
||||
{
|
||||
if (bytes == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
ms.Write(bytes, 0, bytes.Length);
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
BinaryFormatter binaryFormatter = new BinaryFormatter();
|
||||
return binaryFormatter.Deserialize(ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Hncore.Infrastructure.Data;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class CheckHelper
|
||||
{
|
||||
public static void NotNull(object obj, string message = "")
|
||||
{
|
||||
if (ReferenceEquals(obj, null))
|
||||
{
|
||||
if (string.IsNullOrEmpty(message))
|
||||
{
|
||||
message = nameof(obj) + "空引用";
|
||||
}
|
||||
|
||||
throw new BusinessException(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void NotEmpty(string obj, string message = "")
|
||||
{
|
||||
NotNull(obj,message);
|
||||
|
||||
if (obj.Trim() == "")
|
||||
{
|
||||
if (string.IsNullOrEmpty(message))
|
||||
{
|
||||
message = nameof(obj) + "值不能为空";
|
||||
}
|
||||
|
||||
throw new BusinessException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Ext
|
||||
{
|
||||
public static void Check(this ModelStateDictionary dic)
|
||||
{
|
||||
if (!dic.IsValid)
|
||||
{
|
||||
var errs = dic.Values.SelectMany(x => x.Errors);
|
||||
|
||||
string msg = "";
|
||||
|
||||
errs.Select(t => t.Exception.Message).ToList().ForEach((s => { msg += s + "\r\n"; }));
|
||||
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Dapper;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class ConcurrentHelper
|
||||
{
|
||||
private static string _connString = "";
|
||||
private static string _tableName = "concurrent_helper";
|
||||
|
||||
private List<string> _infos = new List<string>();
|
||||
|
||||
private string _id;
|
||||
|
||||
public static void Init(string mysqlConn)
|
||||
{
|
||||
_connString = mysqlConn;
|
||||
|
||||
MySqlHelper.Execute(_connString
|
||||
, $@"create table if not exists {_tableName}
|
||||
(
|
||||
Id VARCHAR(32) PRIMARY KEY UNIQUE,
|
||||
CreateTime datetime DEFAULT now(),
|
||||
Info text
|
||||
)"
|
||||
);
|
||||
}
|
||||
|
||||
public ConcurrentHelper AddInfo(string info)
|
||||
{
|
||||
_infos.Add(info);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private async Task<bool> GetAuthority()
|
||||
{
|
||||
try
|
||||
{
|
||||
string info = ListHelper<string>.ListToStr(_infos, "\n");
|
||||
_id = SecurityHelper.GetMd5Hash(info);
|
||||
|
||||
string sql = $"insert into {_tableName}(Id,Info) values(@Id,@Info)";
|
||||
|
||||
await MySqlHelper.ExecuteAsync(_connString, sql, new {Id = _id, Info = info});
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task Execute(Action action)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (await GetAuthority())
|
||||
{
|
||||
action();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await MySqlHelper.ExecuteAsync(_connString, $"DELETE FROM {_tableName} where Id='{_id}'");
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件类型
|
||||
/// </summary>
|
||||
public class ContentTypeHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 图片格式
|
||||
/// </summary>
|
||||
public static List<string> ImageList = new List<string>()
|
||||
{
|
||||
"image/jpeg",
|
||||
"application/x-jpe",
|
||||
"application/x-jpg",
|
||||
"application/x-bmp",
|
||||
"image/png",
|
||||
"application/x-png",
|
||||
"image/gif"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 视频格式
|
||||
/// </summary>
|
||||
public static List<string> VideoList = new List<string>()
|
||||
{
|
||||
"video/mpeg4",
|
||||
"video/avi",
|
||||
"video/x-ms-wmv",
|
||||
"video/x-mpeg",
|
||||
"video/mpeg4",
|
||||
"video/x-sgi-movie",
|
||||
"application/vnd.rn-realmedia",
|
||||
"application/x-shockwave-flash",
|
||||
"application/vnd.rn-realmedia-vbr",
|
||||
"application/octet-stream",
|
||||
"flv-application/octet-stream",
|
||||
"video/mpg",
|
||||
"video/mpeg",
|
||||
"video/mp4",
|
||||
"video/x-msvideo"
|
||||
};
|
||||
|
||||
#region 得到文件类型
|
||||
|
||||
/// <summary>
|
||||
/// 得到文件类型
|
||||
/// </summary>
|
||||
/// <param name="contentType">文件类型</param>
|
||||
/// <returns></returns>
|
||||
public static FileTypeEnum GetFileType(string contentType)
|
||||
{
|
||||
if (ImageList.Contains(contentType))
|
||||
{
|
||||
return FileTypeEnum.Img;
|
||||
}
|
||||
|
||||
if (VideoList.Contains(contentType))
|
||||
{
|
||||
return FileTypeEnum.Video;
|
||||
}
|
||||
|
||||
return FileTypeEnum.Unknow;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件类型
|
||||
/// </summary>
|
||||
public enum FileTypeEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// 未知
|
||||
/// </summary>
|
||||
[Description("未知")] Unknow = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 图片
|
||||
/// </summary>
|
||||
[Description("图片")] Img = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 音频
|
||||
/// </summary>
|
||||
[Description("音频")] Audio = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 视频
|
||||
/// </summary>
|
||||
[Description("视频")] Video = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 其他
|
||||
/// </summary>
|
||||
[Description("其他")] Other = 4
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class DateTimeHelper
|
||||
{
|
||||
public static DateTime SqlMinTime => Convert.ToDateTime("1975-01-01 00:00:00");
|
||||
|
||||
public static DateTime SqlMaxTime => Convert.ToDateTime("9999-12-31 23:59:59");
|
||||
|
||||
/// <summary>
|
||||
/// 将10位时间戳转时间
|
||||
/// </summary>
|
||||
/// <param name="unixTimeStamp"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime UnixTimeStampToDateTime(long unixTimeStamp)
|
||||
{
|
||||
// Unix timestamp is seconds past epoch
|
||||
DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||
dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
|
||||
return dtDateTime;
|
||||
}
|
||||
|
||||
public static long ToUnixTimestamp(DateTime target)
|
||||
{
|
||||
return Convert.ToInt64((TimeZoneInfo.ConvertTimeToUtc(target) -
|
||||
new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将13位时间戳转为时间
|
||||
/// </summary>
|
||||
/// <param name="javaTimeStamp"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime JsTimeStampToDateTime(double javaTimeStamp)
|
||||
{
|
||||
var dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||
dtDateTime = dtDateTime.AddMilliseconds(javaTimeStamp).ToLocalTime();
|
||||
return dtDateTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取时间戳
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="bflag">为真时获取10位时间戳,为假时获取13位时间戳</param>
|
||||
/// <returns></returns>
|
||||
public static long ToUnixTime(DateTime target, bool bflag = false)
|
||||
{
|
||||
TimeSpan ts = target - new DateTime(1970, 1, 1, 0, 0, 0, 0);
|
||||
long timer = 0;
|
||||
timer = Convert.ToInt64(!bflag ? ts.TotalSeconds : ts.TotalMilliseconds);
|
||||
return timer;
|
||||
}
|
||||
|
||||
public static TimeZoneInfo GetCstTimeZoneInfo()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
return TimeZoneInfo.FindSystemTimeZoneById("Asia/Shanghai");
|
||||
}
|
||||
|
||||
return TimeZoneInfo.FindSystemTimeZoneById("China Standard Time");
|
||||
}
|
||||
|
||||
public static bool IsSameDayOrLess(DateTime dt1, DateTime dt2)
|
||||
{
|
||||
return dt1.Year == dt2.Year
|
||||
&& dt1.Month == dt2.Month
|
||||
&& dt1.Day == dt2.Day
|
||||
|| dt1 < dt2;
|
||||
}
|
||||
|
||||
public static DateTime GetDatePart(DateTime dt)
|
||||
{
|
||||
return new DateTime(dt.Year, dt.Month, dt.Day);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace Hncore.Infrastructure.Utils
|
||||
{
|
||||
public static class DebugClass
|
||||
{
|
||||
public static string PrintStack(bool isOutToDebugWin)
|
||||
{
|
||||
StackFrame[] stacks = new StackTrace().GetFrames();
|
||||
StringBuilder result = new StringBuilder();
|
||||
foreach (StackFrame stack in stacks)
|
||||
{
|
||||
result.AppendFormat("{0} {1} {2} {3}{4}",
|
||||
stack.GetFileName(),
|
||||
stack.GetFileLineNumber(),
|
||||
stack.GetFileColumnNumber(),
|
||||
stack.GetMethod().ToString(),
|
||||
Environment.NewLine
|
||||
);
|
||||
}
|
||||
if (isOutToDebugWin)
|
||||
Debug.WriteLine(result);
|
||||
return result.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Hncore.Infrastructure.Common.DingTalk
|
||||
{
|
||||
public class DingTalkHelper
|
||||
{
|
||||
private static HttpClient _httpClient = new HttpClient(new HttpClientHandler() {UseProxy = false})
|
||||
{Timeout = TimeSpan.FromMinutes(1)};
|
||||
|
||||
static DingTalkHelper()
|
||||
{
|
||||
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
}
|
||||
|
||||
public static Task SendMessage(object message)
|
||||
{
|
||||
return null;
|
||||
// return _httpClient.PostAsync("https://oapi.dingtalk.com/robot/send?access_token=33", JsonContent(message));
|
||||
}
|
||||
|
||||
private static StringContent JsonContent(object obj)
|
||||
{
|
||||
return new StringContent(obj.ToJson(), Encoding.UTF8, "application/json");
|
||||
}
|
||||
|
||||
|
||||
private static async Task<bool> CheckSuccess(HttpResponseMessage res)
|
||||
{
|
||||
var content = await res.Content.ReadAsStringAsync();
|
||||
|
||||
JObject jObject = JsonConvert.DeserializeObject<JObject>(content);
|
||||
|
||||
if (jObject["errmsg"].ToString() == "ok" && Convert.ToInt32(jObject["errcode"]) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 此消息类型为固定text
|
||||
/// </summary>
|
||||
public class TextModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 此消息类型为固定text
|
||||
/// </summary>
|
||||
public string msgtype => "text";
|
||||
|
||||
/// <summary>
|
||||
/// 消息内容
|
||||
/// </summary>
|
||||
public text text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// @人
|
||||
/// </summary>
|
||||
public atText at { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 消息内容
|
||||
/// </summary>
|
||||
public class text
|
||||
{
|
||||
/// <summary>
|
||||
/// 消息内容
|
||||
/// </summary>
|
||||
public string content { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// @人
|
||||
/// </summary>
|
||||
public class atText
|
||||
{
|
||||
/// <summary>
|
||||
/// 被@人的手机号
|
||||
/// </summary>
|
||||
public List<string> atMobiles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// @所有人时:true,否则为:false
|
||||
/// </summary>
|
||||
public bool isAtAll { get; set; } = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 此消息类型为固定markdown
|
||||
/// </summary>
|
||||
public class MarkDownModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 此消息类型为固定markdown
|
||||
/// </summary>
|
||||
public string msgtype => "markdown";
|
||||
|
||||
/// <summary>
|
||||
/// 消息内容
|
||||
/// </summary>
|
||||
public markdown markdown { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// @人
|
||||
/// </summary>
|
||||
public atMarkdown at { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 消息内容
|
||||
/// </summary>
|
||||
public class markdown
|
||||
{
|
||||
/// <summary>
|
||||
/// 标题
|
||||
/// </summary>
|
||||
public string title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 消息内容
|
||||
/// </summary>
|
||||
public string text { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// @人
|
||||
/// </summary>
|
||||
public class atMarkdown
|
||||
{
|
||||
/// <summary>
|
||||
/// 被@人的手机号
|
||||
/// </summary>
|
||||
public List<string> atMobiles { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// @所有人时:true,否则为:false
|
||||
/// </summary>
|
||||
public bool isAtAll { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class EnvironmentVariableHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前环境是否为生产模式
|
||||
/// </summary>
|
||||
public static bool IsAspNetCoreProduction => Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Production";
|
||||
|
||||
public static string HostName => Environment.GetEnvironmentVariable("HOSTNAME");
|
||||
}
|
||||
}
|
||||
@@ -1,644 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using AngleSharp;
|
||||
using AngleSharp.Dom;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NPOI.HSSF.UserModel;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public static class ExcelHelper
|
||||
{
|
||||
public static async Task<Stream> GetStreamFromHtml(string html)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
|
||||
HSSFWorkbook book = new HSSFWorkbook();
|
||||
|
||||
var context = BrowsingContext.New(Configuration.Default);
|
||||
|
||||
var document = await context.OpenAsync(req => req.Content(html));
|
||||
|
||||
try
|
||||
{
|
||||
var tables = document.GetElementsByTagName("table");
|
||||
|
||||
foreach (var table in tables)
|
||||
{
|
||||
var sheetName = table.GetAttribute("sheetname");
|
||||
|
||||
var sheet = book.CreateSheet(sheetName);
|
||||
|
||||
var trs = table.GetElementsByTagName("tr");
|
||||
|
||||
var rowIndex = 0;
|
||||
|
||||
foreach (var tr in trs)
|
||||
{
|
||||
var row = sheet.CreateRow(rowIndex);
|
||||
|
||||
var tds = tr.GetElementsByTagName("td");
|
||||
|
||||
var columnIndex = 0;
|
||||
|
||||
foreach (var td in tds)
|
||||
{
|
||||
row.CreateCell(columnIndex).SetCellValue(td.InnerHtml.Trim());
|
||||
|
||||
columnIndex++;
|
||||
}
|
||||
|
||||
rowIndex++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
book.Write(ms);
|
||||
ms.Position = 0;
|
||||
}
|
||||
finally
|
||||
{
|
||||
document.Close();
|
||||
document.Dispose();
|
||||
|
||||
context.Active.Close();
|
||||
context.Active.Dispose();
|
||||
|
||||
document = null;
|
||||
context = null;
|
||||
|
||||
book.Clear();
|
||||
book.Close();
|
||||
book = null;
|
||||
}
|
||||
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
public static async Task ResponseExcelFromHtml(this ControllerBase controllerBase, string fileName, string html)
|
||||
{
|
||||
using (var ms = await GetStreamFromHtml(html))
|
||||
{
|
||||
var bytes = ms.StreamToBytes();
|
||||
|
||||
var response = controllerBase.HttpContext.Response;
|
||||
|
||||
response.ContentType = "application/octet-stream";
|
||||
response.Headers.Add("Content-Disposition", $"attachment; filename={fileName.UrlEncode()}");
|
||||
response.Headers.Add("X-Suggested-Filename", fileName.UrlEncode());
|
||||
response.Headers.Add("Content-Length", bytes.Length.ToString());
|
||||
|
||||
await response.Body.WriteAsync(bytes, 0, bytes.Length);
|
||||
await response.Body.FlushAsync();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// excel二进制文件转二维string结合
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="st"></param>
|
||||
/// <returns></returns>
|
||||
public static List<List<string>> ReadFromStream(Stream stream, int st = 0)
|
||||
{
|
||||
//根据路径通过已存在的excel来创建HSSFWorkbook,即整个excel文档
|
||||
HSSFWorkbook workbook;
|
||||
try
|
||||
{
|
||||
workbook = new HSSFWorkbook(stream);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error("ReadFromStream",ex);
|
||||
throw new BusinessException("文件读取错误!");
|
||||
}
|
||||
List<List<string>> lis1 = new List<List<string>>();
|
||||
{
|
||||
//获取excel的第一个sheet
|
||||
var sheet = workbook.GetSheetAt(st);
|
||||
if (sheet == null)
|
||||
throw new BusinessException("该文件内没有包含任何工作簿");
|
||||
//获取sheet的首行
|
||||
var headerRow = sheet.GetRow(0);
|
||||
//一行最后一个方格的编号 即总的列数
|
||||
int cellCount = headerRow.LastCellNum;
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i <= sheet.LastRowNum; i++)
|
||||
{
|
||||
List<string> lis = new List<string>();
|
||||
var row = sheet.GetRow(i);
|
||||
if (row == null)
|
||||
continue;
|
||||
for (int j = 0; j < cellCount; j++)
|
||||
{
|
||||
var cell = row.GetCell(j);
|
||||
if (cell == null)
|
||||
{
|
||||
lis.Add("");
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
switch (cell.CellType)
|
||||
{
|
||||
case NPOI.SS.UserModel.CellType.Unknown:
|
||||
lis.Add("Unknown");
|
||||
break;
|
||||
case NPOI.SS.UserModel.CellType.Numeric:
|
||||
if (HSSFDateUtil.IsCellDateFormatted(cell))//对日期格式进行特殊对待
|
||||
lis.Add(HSSFDateUtil.GetJavaDate(cell.NumericCellValue).ToString());
|
||||
else
|
||||
lis.Add(cell.NumericCellValue.ToString());
|
||||
break;
|
||||
case NPOI.SS.UserModel.CellType.String:
|
||||
lis.Add(cell.StringCellValue.ToString());
|
||||
break;
|
||||
case NPOI.SS.UserModel.CellType.Formula:
|
||||
lis.Add(cell.CellFormula.ToString());
|
||||
break;
|
||||
case NPOI.SS.UserModel.CellType.Blank:
|
||||
lis.Add("");
|
||||
break;
|
||||
case NPOI.SS.UserModel.CellType.Boolean:
|
||||
lis.Add(cell.BooleanCellValue.ToString());
|
||||
break;
|
||||
case NPOI.SS.UserModel.CellType.Error:
|
||||
lis.Add(cell.ErrorCellValue.ToString());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
lis.Add("");
|
||||
}
|
||||
}
|
||||
|
||||
//如果本行所有单元格都是空,就跳过本行
|
||||
if (lis.All(item => string.IsNullOrEmpty(item)))
|
||||
continue;
|
||||
|
||||
lis1.Add(lis);
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
LogHelper.Error("ReadFromStream", ex);
|
||||
throw new BusinessException("文件格式错误!");
|
||||
}
|
||||
}
|
||||
#region 细节化处理
|
||||
lis1 = lis1.Where(s => !s.TrueForAll(f => string.IsNullOrWhiteSpace(f))).ToList();//去除全是空格的空行。
|
||||
lis1 = lis1.Select(s => s = s.Select(y => y = y.Trim()).ToList()).ToList();//去除空格
|
||||
if (lis1.Count == 1) throw new Exception("Excel中无有效数据!");
|
||||
#endregion
|
||||
return lis1;
|
||||
}
|
||||
/// <summary>
|
||||
/// 导出列表到excel
|
||||
/// 导出到sheet的数据一致
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="excelData">每一个sheet的数据</param>
|
||||
/// <param name="excelTitle">列表的属性和名称值</param>
|
||||
/// <returns></returns>
|
||||
public static byte[] ExportListToExcel<T>(List<ExcelData<T>> excelData, List<ExcelTitle> excelTitle)
|
||||
{
|
||||
var workbook = new NPOI.XSSF.UserModel.XSSFWorkbook();
|
||||
|
||||
var entityType = typeof(T);
|
||||
PropertyInfo[] entityProperties = entityType.GetProperties();
|
||||
|
||||
if (excelData == null || excelData.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
foreach (var item in excelData)
|
||||
{
|
||||
#region MyRegion
|
||||
//var sheet = workbook.CreateSheet(item.SheetName.Replace('/','-'));
|
||||
//var titleRow = sheet.CreateRow(0);
|
||||
//for (int i = 0; i < excelTitle.Count; i++)
|
||||
//{
|
||||
// titleRow.CreateCell(i).SetCellValue(excelTitle[i].Title);
|
||||
//}
|
||||
//var sheetData = item.Data;
|
||||
//for (int j = 0; j < sheetData.Count; j++)
|
||||
//{
|
||||
// var dataRow = sheet.CreateRow(j + 1);
|
||||
// for (int i = 0; i < excelTitle.Count; i++)
|
||||
// {
|
||||
// if (excelTitle[i].Property.ToUpper().Equals("ID"))
|
||||
// {
|
||||
// var num = j + 1;
|
||||
// dataRow.CreateCell(i).SetCellValue(num);
|
||||
// continue;
|
||||
// }
|
||||
// var entityProperty = entityProperties.FirstOrDefault(m => m.Name == excelTitle[i].Property);
|
||||
|
||||
// var cellVal = entityProperty?.GetValue(sheetData[j]);
|
||||
// if (cellVal?.GetType().Name == "DateTime")
|
||||
// {
|
||||
// dataRow.CreateCell(i).SetCellValue(((DateTime?)cellVal)?.ToString("yyyy/MM/dd HH:mm:ss"));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// dataRow.CreateCell(i).SetCellValue(cellVal?.ToString());
|
||||
// }
|
||||
// //dataRow.CreateCell(i).SetCellValue(cellVal?.ToString());
|
||||
// }
|
||||
//}
|
||||
#endregion
|
||||
CreateSheetData(workbook, item, excelTitle, entityProperties);
|
||||
}
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
workbook.Write(ms);
|
||||
var bytes = ms.ToArray();
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
LogHelper.Error("ExportListToExcel=>" + ex);
|
||||
|
||||
throw ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
workbook.Clear();
|
||||
workbook.Close();
|
||||
workbook = null;
|
||||
}
|
||||
}
|
||||
public static byte[] ExportListToExcel<T>(ExcelData<T> excelData, List<ExcelTitle> excelTitle)
|
||||
{
|
||||
var workbook = new NPOI.XSSF.UserModel.XSSFWorkbook();
|
||||
|
||||
var entityType = typeof(T);
|
||||
PropertyInfo[] entityProperties = entityType.GetProperties();
|
||||
|
||||
try
|
||||
{
|
||||
#region MyRegion
|
||||
//var sheet = workbook.CreateSheet(excelData.SheetName.Replace('/', '-'));
|
||||
//var titleRow = sheet.CreateRow(0);
|
||||
//for (int i = 0; i < excelTitle.Count; i++)
|
||||
//{
|
||||
// titleRow.CreateCell(i).SetCellValue(excelTitle[i].Title);
|
||||
//}
|
||||
//var sheetData = excelData.Data;
|
||||
//for (int j = 0; j < sheetData.Count; j++)
|
||||
//{
|
||||
// var dataRow = sheet.CreateRow(j + 1);
|
||||
// for (int i = 0; i < excelTitle.Count; i++)
|
||||
// {
|
||||
// var cellVal = entityProperties.FirstOrDefault(m => m.Name == excelTitle[i].Property)?.GetValue(sheetData[j]);
|
||||
|
||||
// if (cellVal?.GetType().Name == "DateTime")
|
||||
// {
|
||||
// dataRow.CreateCell(i).SetCellValue(((DateTime?)cellVal)?.ToString("yyyy/MM/dd HH:mm:ss"));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// dataRow.CreateCell(i).SetCellValue(cellVal?.ToString());
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
#endregion
|
||||
CreateSheetData(workbook, excelData, excelTitle, entityProperties);
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
workbook.Write(ms);
|
||||
var bytes = ms.ToArray();
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error("ExportListToExcel=>" + ex);
|
||||
|
||||
throw ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
workbook.Clear();
|
||||
workbook.Close();
|
||||
workbook = null;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 创建excel表单数据
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="workbook"></param>
|
||||
/// <param name="excelData"></param>
|
||||
/// <param name="excelTitle"></param>
|
||||
/// <param name="entityProperties"></param>
|
||||
private static void CreateSheetData<T>(NPOI.XSSF.UserModel.XSSFWorkbook workbook,
|
||||
ExcelData<T> excelData, List<ExcelTitle> excelTitle,PropertyInfo[] entityProperties)
|
||||
{
|
||||
var sheet = workbook.CreateSheet(excelData.SheetName.Replace('/', '-'));
|
||||
var titleRow = sheet.CreateRow(0);
|
||||
for (int i = 0; i < excelTitle.Count; i++)
|
||||
{
|
||||
titleRow.CreateCell(i).SetCellValue(excelTitle[i].Title);
|
||||
}
|
||||
var sheetData = excelData.Data;
|
||||
for (int j = 0; j < sheetData.Count; j++)
|
||||
{
|
||||
var dataRow = sheet.CreateRow(j + 1);
|
||||
for (int i = 0; i < excelTitle.Count; i++)
|
||||
{
|
||||
var currentTitle = excelTitle[i];
|
||||
if (currentTitle.Property.Equals("序号"))
|
||||
{
|
||||
var num = j + 1;
|
||||
dataRow.CreateCell(i).SetCellValue(num);
|
||||
continue;
|
||||
}
|
||||
var cellVal = entityProperties.FirstOrDefault(m => m.Name == currentTitle.Property)?.GetValue(sheetData[j]);
|
||||
if (currentTitle.Format != null)
|
||||
{
|
||||
cellVal = currentTitle.Format(cellVal);
|
||||
}
|
||||
if (currentTitle.Expr != null)
|
||||
{
|
||||
cellVal = currentTitle.Expr(sheetData[j]);
|
||||
}
|
||||
else if (cellVal?.GetType().Name == "DateTime")
|
||||
{
|
||||
dataRow.CreateCell(i).SetCellValue(((DateTime?)cellVal)?.ToString("yyyy/MM/dd HH:mm:ss"));
|
||||
}
|
||||
dataRow.CreateCell(i).SetCellValue(cellVal?.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
#region DownloadAsync(下载)
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 下载
|
||||
/// </summary>
|
||||
/// <param name="stream">流</param>
|
||||
/// <param name="fileName">文件名,包含扩展名</param>
|
||||
public static async Task DownloadAsync(this ControllerBase controllerBase, Stream stream, string fileName)
|
||||
{
|
||||
await DownloadAsync(controllerBase,stream, fileName, Encoding.UTF8);
|
||||
}
|
||||
/// <summary>
|
||||
/// 下载
|
||||
/// </summary>
|
||||
/// <param name="stream">流</param>
|
||||
/// <param name="fileName">文件名,包含扩展名</param>
|
||||
/// <param name="encoding">字符编码</param>
|
||||
public static async Task DownloadAsync(this ControllerBase controllerBase, Stream stream, string fileName, Encoding encoding)
|
||||
{
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
var buffer = new byte[stream.Length];
|
||||
stream.Read(buffer, 0, buffer.Length);
|
||||
|
||||
await DownloadAsync(controllerBase, buffer, fileName, encoding);
|
||||
}
|
||||
/// <summary>
|
||||
/// 下载
|
||||
/// </summary>
|
||||
/// <param name="bytes">字节流</param>
|
||||
/// <param name="fileName">文件名,包含扩展名</param>
|
||||
public static async Task DownloadAsync(this ControllerBase controllerBase, byte[] bytes, string fileName)
|
||||
{
|
||||
await DownloadAsync(controllerBase,bytes, fileName, Encoding.UTF8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载
|
||||
/// </summary>
|
||||
/// <param name="bytes">字节流</param>
|
||||
/// <param name="fileName">文件名,包含扩展名</param>
|
||||
/// <param name="encoding">字符编码</param>
|
||||
public static async Task DownloadAsync(this ControllerBase controllerBase,byte[] bytes, string fileName, Encoding encoding)
|
||||
{
|
||||
var response = controllerBase.HttpContext.Response;
|
||||
if (bytes == null || bytes.Length == 0)
|
||||
return;
|
||||
fileName = fileName.Replace(" ", "");
|
||||
fileName = HttpUtility.UrlEncode(fileName, encoding);
|
||||
response.ContentType = "application/octet-stream";
|
||||
response.Headers.Add("Content-Disposition", $"attachment; filename={fileName}");
|
||||
response.Headers.Add("Content-Length", bytes.Length.ToString());
|
||||
response.Headers.Add("X-Suggested-Filename", fileName);
|
||||
await response.Body.WriteAsync(bytes, 0, bytes.Length);
|
||||
await response.Body.FlushAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class ExcelTitle
|
||||
{
|
||||
/// <summary>
|
||||
/// 导出数据对应的 属性字段名
|
||||
/// </summary>
|
||||
public string Property { get; set; }
|
||||
/// <summary>
|
||||
/// excel 的title
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
public Func<object, object> Format { get; set; }
|
||||
public Func<object, object> Expr { get; set; }
|
||||
}
|
||||
public class ExcelData<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 导出数据对应的 属性字段名
|
||||
/// </summary>
|
||||
public string SheetName { get; set; }
|
||||
/// <summary>
|
||||
/// excel 的title
|
||||
/// </summary>
|
||||
public List<T> Data { get; set; }
|
||||
}
|
||||
#region Excel导入验证
|
||||
/// <summary>
|
||||
/// Excel导入验证
|
||||
/// </summary>
|
||||
public static class ValidForExcel
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 解析字符串到int32、double、datetime...
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="rowNo"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="isCanNullOrEmpty"></param>
|
||||
/// <param name="isPositiveOrZero">自然数0,1,2,3...</param>
|
||||
/// <returns></returns>
|
||||
public static T ValidParseStr<T>(string str,string message = "数据", bool isCanNullOrEmpty = true, bool isPositiveOrZero = true)
|
||||
{
|
||||
var val = default(T);
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
if (isCanNullOrEmpty)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"{message}不能为空");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (typeof(T).Name == typeof(int).Name || typeof(T).FullName == typeof(int?).FullName)
|
||||
{
|
||||
if (int.TryParse(str, out var valueInt))
|
||||
{
|
||||
if (isPositiveOrZero && valueInt < 0)
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
return (T)Convert.ChangeType(valueInt, TypeCode.Int32);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (typeof(T).Name == typeof(Decimal).Name || typeof(T).FullName == typeof(Decimal?).FullName)
|
||||
{
|
||||
if (Decimal.TryParse(str, out var valueInt))
|
||||
{
|
||||
if (isPositiveOrZero && valueInt < 0)
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
return (T)Convert.ChangeType(valueInt, TypeCode.Decimal);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (typeof(T).Name == typeof(Double).Name || typeof(T).FullName == typeof(Double?).FullName)
|
||||
{
|
||||
if (Double.TryParse(str, out var valueInt))
|
||||
{
|
||||
if (isPositiveOrZero && valueInt < 0)
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
return (T)Convert.ChangeType(valueInt, TypeCode.Double);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (typeof(T).Name == typeof(Single).Name || typeof(T).FullName == typeof(Single?).FullName)
|
||||
{
|
||||
if (Single.TryParse(str, out var valueInt))
|
||||
{
|
||||
if (isPositiveOrZero && valueInt < 0)
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
return (T)Convert.ChangeType(valueInt, TypeCode.Single);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (typeof(T).Name == typeof(DateTime).Name || typeof(T).FullName == typeof(DateTime?).FullName)
|
||||
{
|
||||
if (DateTime.TryParse(str, out var valueInt))
|
||||
{
|
||||
return (T)Convert.ChangeType(valueInt, TypeCode.DateTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
return val;
|
||||
error: throw new Exception($"{message}的值有误");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提供正则、提示信息,返回验证结果
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="rowNo"></param>
|
||||
/// <param name="pattern"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="isCanNullOrEmpty"></param>
|
||||
/// <returns></returns>
|
||||
public static string ValidByPattern(string str,string pattern, string message = "数据", bool isCanNullOrEmpty = true)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
if (isCanNullOrEmpty)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new BusinessException($"{message}不能为空");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Regex.IsMatch(str, pattern)) throw new BusinessException($"{message}输入有误");
|
||||
return str;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据枚举判断
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="str"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="isCanNullOrEmpty"></param>
|
||||
/// <returns></returns>
|
||||
public static int? ValidByEnum<T>(string str, string message, bool isCanNullOrEmpty = true) //where T:Enum
|
||||
{
|
||||
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
if (isCanNullOrEmpty)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new BusinessException($"{message}不能为空");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var value = EnumExtension.EnumToList<T>().Find(s => s.Name == str)?.Value;
|
||||
if (value == null) throw new BusinessException($"未知的数据:{str}");
|
||||
return Convert.ToInt32(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public static class HttpHelp
|
||||
{
|
||||
/// <summary>
|
||||
/// get请求
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public static string HttpGet(string url)
|
||||
{
|
||||
string result = string.Empty;
|
||||
try
|
||||
{
|
||||
HttpWebRequest wbRequest = (HttpWebRequest)WebRequest.Create(url);
|
||||
wbRequest.Method = "GET";
|
||||
HttpWebResponse wbResponse = (HttpWebResponse)wbRequest.GetResponse();
|
||||
using (Stream responseStream = wbResponse.GetResponseStream())
|
||||
{
|
||||
using (StreamReader sReader = new StreamReader(responseStream))
|
||||
{
|
||||
result = sReader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch/* (Exception ex) 此处暂时屏蔽掉了,要不然编译光弹出变量未使用的警告,谁用得着再打开*/
|
||||
{
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// get 请求,带token
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public static string HttpGet(string token,string url)
|
||||
{
|
||||
string result = string.Empty;
|
||||
try
|
||||
{
|
||||
HttpWebRequest wbRequest = (HttpWebRequest)WebRequest.Create(url);
|
||||
wbRequest.Headers.Add("token", token);
|
||||
wbRequest.Method = "GET";
|
||||
HttpWebResponse wbResponse = (HttpWebResponse)wbRequest.GetResponse();
|
||||
using (Stream responseStream = wbResponse.GetResponseStream())
|
||||
{
|
||||
using (StreamReader sReader = new StreamReader(responseStream))
|
||||
{
|
||||
result = sReader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch/* (Exception ex) 此处暂时屏蔽掉了,要不然编译光弹出变量未使用的警告,谁用得着再打开*/
|
||||
{
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Qiniu.Storage;
|
||||
using Qiniu.Util;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class ImageCloudHelper
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <returns>图片地址</returns>
|
||||
public static string UploadImage(Stream stream, string prefix)
|
||||
{
|
||||
//todo
|
||||
return "";
|
||||
Mac mac = new Mac("3bmkJLD-inSGpQnLr_9UlommFT81B5L0ryesJLhS", "X22vza-l53jcZyi_fmaex88R065_Ip2_3j5Im0Se");
|
||||
|
||||
string bucket = "property";
|
||||
|
||||
// 上传策略,参见
|
||||
// https://developer.qiniu.com/kodo/manual/put-policy
|
||||
PutPolicy putPolicy = new PutPolicy();
|
||||
// 如果需要设置为"覆盖"上传(如果云端已有同名文件则覆盖),请使用 SCOPE = "BUCKET:KEY"
|
||||
// putPolicy.Scope = bucket + ":" + saveKey;
|
||||
putPolicy.Scope = bucket;
|
||||
// 上传策略有效期(对应于生成的凭证的有效期)
|
||||
putPolicy.SetExpires(3600);
|
||||
|
||||
string jstr = putPolicy.ToJsonString();
|
||||
string token = Auth.CreateUploadToken(mac, jstr);
|
||||
|
||||
FormUploader fu = new FormUploader(new Config()
|
||||
{
|
||||
Zone = Zone.ZONE_CN_East
|
||||
});
|
||||
|
||||
|
||||
string fileName = prefix + Guid.NewGuid() + ".jpg";
|
||||
|
||||
var result = fu.UploadStream(stream, fileName, token, null);
|
||||
|
||||
if (result.Code == 200)
|
||||
{
|
||||
return "http://propertyimages.etor.vip/" + fileName;
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string UploadImage(string imageBase64, string prefix)
|
||||
{
|
||||
byte[] imageByte = Convert.FromBase64String(imageBase64);
|
||||
|
||||
var stream = new MemoryStream(imageByte);
|
||||
|
||||
return UploadImage(stream, prefix);
|
||||
}
|
||||
|
||||
public static string GetToken(int expireInSeconds=3600)
|
||||
{
|
||||
Mac mac = new Mac("3bmkJLD-inSGpQnLr_9UlommFT81B5L0ryesJLhS", "X22vza-l53jcZyi_fmaex88R065_Ip2_3j5Im0Se");
|
||||
|
||||
string bucket = "property";
|
||||
|
||||
// 上传策略,参见
|
||||
// https://developer.qiniu.com/kodo/manual/put-policy
|
||||
PutPolicy putPolicy = new PutPolicy();
|
||||
// 如果需要设置为"覆盖"上传(如果云端已有同名文件则覆盖),请使用 SCOPE = "BUCKET:KEY"
|
||||
// putPolicy.Scope = bucket + ":" + saveKey;
|
||||
putPolicy.Scope = bucket;
|
||||
// 上传策略有效期(对应于生成的凭证的有效期)
|
||||
putPolicy.SetExpires(expireInSeconds);
|
||||
putPolicy.ReturnBody = "{\"key\":$(key),\"hash\":$(etag),\"mimeType\":$(mimeType),\"fname\":$(fname),\"fsize\":$(fsize),\"avinfo\":$(avinfo),\"ext\":$(ext),\"imageInfo\":$(imageInfo)}";
|
||||
|
||||
string jstr = putPolicy.ToJsonString();
|
||||
string token = Auth.CreateUploadToken(mac, jstr);
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class IoHelper
|
||||
{
|
||||
#region 数据流转字节数组
|
||||
|
||||
/// <summary>
|
||||
/// 数据流转字节数组
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] StreamToBytes(this Stream stream)
|
||||
{
|
||||
byte[] bytes = new byte[stream.Length];
|
||||
stream.Read(bytes, 0, bytes.Length);
|
||||
// 设置当前流的位置为流的开始
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 将 byte[] 转成 Stream
|
||||
|
||||
public static Stream BytesToStream(this byte[] bytes)
|
||||
|
||||
{
|
||||
Stream stream = new MemoryStream(bytes);
|
||||
return stream;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public static class ListHelper<T>
|
||||
{
|
||||
#region 字符串转化为泛型集合
|
||||
|
||||
/// <summary>
|
||||
/// 字符串转化为泛型集合
|
||||
/// </summary>
|
||||
/// <param name="str">字符串</param>
|
||||
/// <param name="splitstr">要分割的字符</param>
|
||||
/// <returns></returns>
|
||||
public static List<T> StrToList(string str, char splitstr)
|
||||
{
|
||||
List<T> list = new List<T>();
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
return list;
|
||||
}
|
||||
if (!str.Contains(splitstr))
|
||||
{
|
||||
list.Add((T)Convert.ChangeType(str, typeof(T)));
|
||||
return list;
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] strarray = str.Split(splitstr);
|
||||
|
||||
foreach (string s in strarray)
|
||||
{
|
||||
if (s != "")
|
||||
list.Add((T)Convert.ChangeType(s, typeof(T)));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字符串转化为泛型集合
|
||||
/// </summary>
|
||||
/// <param name="str">字符串</param>
|
||||
/// <returns></returns>
|
||||
public static List<T> StrToList(string str)
|
||||
{
|
||||
return StrToList(str, ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static string ListToStr(List<T> list, string splitstr=",")
|
||||
{
|
||||
string str = "";
|
||||
|
||||
list.ForEach(t =>
|
||||
{
|
||||
str += t + splitstr;
|
||||
});
|
||||
|
||||
if (str.EndsWith(splitstr))
|
||||
{
|
||||
str = str.Substring(0, str.Length - splitstr.Length);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#region 转换几个中所有元素的类型
|
||||
|
||||
/// <summary>
|
||||
/// 转换几个中所有元素的类型
|
||||
/// </summary>
|
||||
/// <typeparam name="To"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
public static List<To> ConvertListType<To>(List<T> list)
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<To> newlist = new List<To>();
|
||||
foreach (T t in list)
|
||||
{
|
||||
object to = new object();
|
||||
if (typeof(To).Name == "Guid")
|
||||
{
|
||||
to = Guid.Parse(t.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
to = Convert.ChangeType(t, typeof(To));
|
||||
}
|
||||
newlist.Add((To)to);
|
||||
}
|
||||
return newlist;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转化一个DataTable
|
||||
|
||||
/// <summary>
|
||||
/// 转化一个DataTable
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
public static DataTable ToDataTable(IEnumerable<T> list)
|
||||
{
|
||||
//创建属性的集合
|
||||
List<PropertyInfo> pList = new List<PropertyInfo>();
|
||||
//获得反射的入口
|
||||
Type type = typeof(T);
|
||||
DataTable dt = new DataTable();
|
||||
//把所有的public属性加入到集合 并添加DataTable的列
|
||||
Array.ForEach(type.GetProperties(), p => { pList.Add(p); dt.Columns.Add(p.Name, p.PropertyType); });
|
||||
foreach (var item in list)
|
||||
{
|
||||
//创建一个DataRow实例
|
||||
DataRow row = dt.NewRow();
|
||||
//给row 赋值
|
||||
pList.ForEach(p => row[p.Name] = p.GetValue(item, null));
|
||||
//加入到DataTable
|
||||
dt.Rows.Add(row);
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using System;
|
||||
using NLog;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class LogHelper
|
||||
{
|
||||
private static readonly Logger Log = LogManager.GetLogger("UserLog");
|
||||
private static string assName = AppDomain.CurrentDomain.FriendlyName;
|
||||
|
||||
private static string FormatMsg(string title, object msg)
|
||||
{
|
||||
return "Assembly:" + assName + "\r\nTitle : " + title + "\r\nMessage : " + msg + "\r\n";
|
||||
}
|
||||
|
||||
public static void Error(string title, object msg = null)
|
||||
{
|
||||
Log?.Error(FormatMsg(title, msg));
|
||||
|
||||
Console.WriteLine(DateTime.Now+"\r\n"+FormatMsg(title, msg));
|
||||
}
|
||||
|
||||
public static void Debug(string title, object msg = null)
|
||||
{
|
||||
Log?.Debug(FormatMsg(title, msg));
|
||||
|
||||
Console.WriteLine(DateTime.Now+"\r\n"+FormatMsg(title, msg));
|
||||
}
|
||||
|
||||
public static void Info(string title, object msg = null)
|
||||
{
|
||||
Log?.Info(FormatMsg(title, msg));
|
||||
|
||||
Console.WriteLine(DateTime.Now+"\r\n"+FormatMsg(title, msg));
|
||||
}
|
||||
|
||||
public static void Warn(string title, object msg = null)
|
||||
{
|
||||
Log?.Warn(FormatMsg(title, msg));
|
||||
|
||||
Console.WriteLine(DateTime.Now+"\r\n"+FormatMsg(title, msg));
|
||||
}
|
||||
|
||||
public static void Trace(string title, object msg = null)
|
||||
{
|
||||
Log?.Trace(FormatMsg(title, msg));
|
||||
|
||||
Console.WriteLine(DateTime.Now+"\r\n"+FormatMsg(title, msg));
|
||||
}
|
||||
|
||||
public static void Fatal(string title, object msg = null)
|
||||
{
|
||||
Log?.Fatal(FormatMsg(title, msg));
|
||||
|
||||
Console.WriteLine(DateTime.Now+"\r\n"+FormatMsg(title, msg));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Dapper;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class MySqlHelper
|
||||
{
|
||||
public static int Execute(string connStr, string sql, object param = null)
|
||||
{
|
||||
using (var conn = new MySqlConnection(connStr))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
return conn.Execute(sql, param);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<int> ExecuteAsync(string connStr, string sql, object param = null)
|
||||
{
|
||||
using (var conn = new MySqlConnection(connStr))
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
return await conn.ExecuteAsync(sql, param);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class NetworkHelper
|
||||
{
|
||||
public static string GetPublicIp()
|
||||
{
|
||||
return NetworkInterface
|
||||
.GetAllNetworkInterfaces()
|
||||
.Select(p => p.GetIPProperties())
|
||||
.SelectMany(p => p.UnicastAddresses)
|
||||
.FirstOrDefault(p =>
|
||||
p.Address.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(p.Address))?.Address
|
||||
.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Qiniu.Http;
|
||||
using Qiniu.Storage;
|
||||
using Qiniu.Util;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class QiNiuCloudHelper
|
||||
{
|
||||
static Mac mac = new Mac("3bmkJLD-inSGpQnLr_9UlommFT81B5L0ryesJLhS",
|
||||
"X22vza-l53jcZyi_fmaex88R065_Ip2_3j5Im0Se");
|
||||
|
||||
static string bucket = "property";
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="bytes"></param>
|
||||
/// <returns>图片地址</returns>
|
||||
public static string UploadImage(Stream stream, string prefix, string persistentOps = "")
|
||||
{
|
||||
string fileName = prefix + Guid.NewGuid() + ".jpg";
|
||||
|
||||
// 上传策略,参见
|
||||
// https://developer.qiniu.com/kodo/manual/put-policy
|
||||
PutPolicy putPolicy = new PutPolicy();
|
||||
// 如果需要设置为"覆盖"上传(如果云端已有同名文件则覆盖),请使用 SCOPE = "BUCKET:KEY"
|
||||
// putPolicy.Scope = bucket + ":" + saveKey;
|
||||
putPolicy.Scope = bucket;
|
||||
// 上传策略有效期(对应于生成的凭证的有效期)
|
||||
putPolicy.SetExpires(3600);
|
||||
|
||||
if (!string.IsNullOrEmpty(persistentOps))
|
||||
{
|
||||
string saveAs = (bucket + ":" + fileName).ToBase64String()
|
||||
.Replace("+", "-")
|
||||
.Replace("/", "_");
|
||||
putPolicy.PersistentOps = persistentOps + $"|saveas/{saveAs}";
|
||||
putPolicy.PersistentPipeline = "face_image";
|
||||
}
|
||||
|
||||
|
||||
string jstr = putPolicy.ToJsonString();
|
||||
string token = Auth.CreateUploadToken(mac, jstr);
|
||||
|
||||
ResumableUploader fu = new ResumableUploader(new Config()
|
||||
{
|
||||
Zone = Zone.ZONE_CN_East
|
||||
});
|
||||
|
||||
|
||||
var result = fu.UploadStream(stream, fileName, token, null);
|
||||
|
||||
if (result.Code == 200)
|
||||
{
|
||||
return "http://propertyimages.etor.vip/" + fileName;
|
||||
}
|
||||
|
||||
LogHelper.Error("七牛上传图片失败", result.ToString());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string UploadImage(string imageBase64, string prefix, string persistentOps = "")
|
||||
{
|
||||
byte[] imageByte = Convert.FromBase64String(imageBase64);
|
||||
|
||||
var stream = new MemoryStream(imageByte);
|
||||
|
||||
return UploadImage(stream, prefix, persistentOps);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除资源
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
public static void Delete(string key)
|
||||
{
|
||||
Config config = new Config();
|
||||
config.Zone = Zone.ZONE_CN_East;
|
||||
|
||||
BucketManager bucketManager = new BucketManager(mac, config);
|
||||
|
||||
var res = bucketManager.Delete(bucket, key);
|
||||
}
|
||||
|
||||
public static List<string> Domains(string bucket)
|
||||
{
|
||||
Config config = new Config();
|
||||
config.Zone = Zone.ZONE_CN_East;
|
||||
|
||||
BucketManager bucketManager = new BucketManager(mac, config);
|
||||
|
||||
return bucketManager.Domains("property").Result;
|
||||
}
|
||||
|
||||
public static string GetToken(int expireInSeconds = 3600)
|
||||
{
|
||||
// 上传策略,参见
|
||||
// https://developer.qiniu.com/kodo/manual/put-policy
|
||||
PutPolicy putPolicy = new PutPolicy();
|
||||
// 如果需要设置为"覆盖"上传(如果云端已有同名文件则覆盖),请使用 SCOPE = "BUCKET:KEY"
|
||||
// putPolicy.Scope = bucket + ":" + saveKey;
|
||||
putPolicy.Scope = bucket;
|
||||
// 上传策略有效期(对应于生成的凭证的有效期)
|
||||
putPolicy.SetExpires(expireInSeconds);
|
||||
putPolicy.ReturnBody =
|
||||
"{\"key\":$(key),\"hash\":$(etag),\"mimeType\":$(mimeType),\"fname\":$(fname),\"fsize\":$(fsize),\"avinfo\":$(avinfo),\"ext\":$(ext),\"imageInfo\":$(imageInfo)}";
|
||||
|
||||
string jstr = putPolicy.ToJsonString();
|
||||
string token = Auth.CreateUploadToken(mac, jstr);
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,333 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// RSA加解密 使用OpenSSL的公钥加密/私钥解密
|
||||
///
|
||||
/// 公私钥请使用openssl生成 ssh-keygen -t rsa 命令生成的公钥私钥是不行的
|
||||
/// </summary>
|
||||
public class RsaHelper
|
||||
{
|
||||
private readonly RSA _privateKeyRsaProvider;
|
||||
private readonly RSA _publicKeyRsaProvider;
|
||||
private readonly HashAlgorithmName _hashAlgorithmName;
|
||||
private readonly Encoding _encoding;
|
||||
|
||||
/// <summary>
|
||||
/// 实例化RSAHelper
|
||||
/// </summary>
|
||||
/// <param name="rsaType">加密算法类型 RSA SHA1;RSA2 SHA256 密钥长度至少为2048</param>
|
||||
/// <param name="encoding">编码类型</param>
|
||||
/// <param name="privateKey">私钥</param>
|
||||
/// <param name="publicKey">公钥</param>
|
||||
public RsaHelper(RsaType rsaType, Encoding encoding, string privateKey, string publicKey = null)
|
||||
{
|
||||
_encoding = encoding;
|
||||
if (!string.IsNullOrEmpty(privateKey))
|
||||
{
|
||||
_privateKeyRsaProvider = CreateRsaProviderFromPrivateKey(privateKey);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(publicKey))
|
||||
{
|
||||
_publicKeyRsaProvider = CreateRsaProviderFromPublicKey(publicKey);
|
||||
}
|
||||
|
||||
_hashAlgorithmName = rsaType == RsaType.RSA ? HashAlgorithmName.SHA1 : HashAlgorithmName.SHA256;
|
||||
}
|
||||
|
||||
#region 使用私钥签名
|
||||
|
||||
/// <summary>
|
||||
/// 使用私钥签名
|
||||
/// </summary>
|
||||
/// <param name="data">原始数据</param>
|
||||
/// <returns></returns>
|
||||
public string Sign(string data)
|
||||
{
|
||||
byte[] dataBytes = _encoding.GetBytes(data);
|
||||
|
||||
var signatureBytes =
|
||||
_privateKeyRsaProvider.SignData(dataBytes, _hashAlgorithmName, RSASignaturePadding.Pkcs1);
|
||||
|
||||
return Convert.ToBase64String(signatureBytes);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 使用公钥验证签名
|
||||
|
||||
/// <summary>
|
||||
/// 使用公钥验证签名
|
||||
/// </summary>
|
||||
/// <param name="data">原始数据</param>
|
||||
/// <param name="sign">签名</param>
|
||||
/// <returns></returns>
|
||||
public bool Verify(string data, string sign)
|
||||
{
|
||||
byte[] dataBytes = _encoding.GetBytes(data);
|
||||
byte[] signBytes = Convert.FromBase64String(sign);
|
||||
|
||||
var verify = _publicKeyRsaProvider.VerifyData(dataBytes, signBytes, _hashAlgorithmName,
|
||||
RSASignaturePadding.Pkcs1);
|
||||
|
||||
return verify;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 解密
|
||||
|
||||
public string Decrypt(string cipherText)
|
||||
{
|
||||
if (_privateKeyRsaProvider == null)
|
||||
{
|
||||
throw new Exception("_privateKeyRsaProvider is null");
|
||||
}
|
||||
|
||||
return Encoding.UTF8.GetString(_privateKeyRsaProvider.Decrypt(Convert.FromBase64String(cipherText),
|
||||
RSAEncryptionPadding.Pkcs1));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 加密
|
||||
|
||||
public string Encrypt(string text)
|
||||
{
|
||||
if (_publicKeyRsaProvider == null)
|
||||
{
|
||||
throw new Exception("_publicKeyRsaProvider is null");
|
||||
}
|
||||
|
||||
return Convert.ToBase64String(_publicKeyRsaProvider.Encrypt(Encoding.UTF8.GetBytes(text),
|
||||
RSAEncryptionPadding.Pkcs1));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 使用私钥创建RSA实例
|
||||
|
||||
public RSA CreateRsaProviderFromPrivateKey(string privateKey)
|
||||
{
|
||||
var privateKeyBits = Convert.FromBase64String(privateKey);
|
||||
|
||||
var rsa = RSA.Create();
|
||||
var rsaParameters = new RSAParameters();
|
||||
|
||||
using (BinaryReader binr = new BinaryReader(new MemoryStream(privateKeyBits)))
|
||||
{
|
||||
byte bt = 0;
|
||||
ushort twobytes = 0;
|
||||
twobytes = binr.ReadUInt16();
|
||||
if (twobytes == 0x8130)
|
||||
binr.ReadByte();
|
||||
else if (twobytes == 0x8230)
|
||||
binr.ReadInt16();
|
||||
else
|
||||
throw new Exception("Unexpected value read binr.ReadUInt16()");
|
||||
|
||||
twobytes = binr.ReadUInt16();
|
||||
if (twobytes != 0x0102)
|
||||
throw new Exception("Unexpected version");
|
||||
|
||||
bt = binr.ReadByte();
|
||||
if (bt != 0x00)
|
||||
throw new Exception("Unexpected value read binr.ReadByte()");
|
||||
|
||||
rsaParameters.Modulus = binr.ReadBytes(GetIntegerSize(binr));
|
||||
rsaParameters.Exponent = binr.ReadBytes(GetIntegerSize(binr));
|
||||
rsaParameters.D = binr.ReadBytes(GetIntegerSize(binr));
|
||||
rsaParameters.P = binr.ReadBytes(GetIntegerSize(binr));
|
||||
rsaParameters.Q = binr.ReadBytes(GetIntegerSize(binr));
|
||||
rsaParameters.DP = binr.ReadBytes(GetIntegerSize(binr));
|
||||
rsaParameters.DQ = binr.ReadBytes(GetIntegerSize(binr));
|
||||
rsaParameters.InverseQ = binr.ReadBytes(GetIntegerSize(binr));
|
||||
}
|
||||
|
||||
rsa.ImportParameters(rsaParameters);
|
||||
return rsa;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 使用公钥创建RSA实例
|
||||
|
||||
public RSA CreateRsaProviderFromPublicKey(string publicKeyString)
|
||||
{
|
||||
// encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
|
||||
byte[] seqOid =
|
||||
{0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00};
|
||||
byte[] seq = new byte[15];
|
||||
|
||||
var x509Key = Convert.FromBase64String(publicKeyString);
|
||||
|
||||
// --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
|
||||
using (MemoryStream mem = new MemoryStream(x509Key))
|
||||
{
|
||||
using (BinaryReader binr = new BinaryReader(mem)
|
||||
) //wrap Memory Stream with BinaryReader for easy reading
|
||||
{
|
||||
byte bt = 0;
|
||||
ushort twobytes = 0;
|
||||
|
||||
twobytes = binr.ReadUInt16();
|
||||
if (twobytes == 0x8130
|
||||
) //data read as little endian order (actual data order for Sequence is 30 81)
|
||||
binr.ReadByte(); //advance 1 byte
|
||||
else if (twobytes == 0x8230)
|
||||
binr.ReadInt16(); //advance 2 bytes
|
||||
else
|
||||
return null;
|
||||
|
||||
seq = binr.ReadBytes(15); //read the Sequence OID
|
||||
if (!CompareBytearrays(seq, seqOid)) //make sure Sequence for OID is correct
|
||||
return null;
|
||||
|
||||
twobytes = binr.ReadUInt16();
|
||||
if (twobytes == 0x8103
|
||||
) //data read as little endian order (actual data order for Bit String is 03 81)
|
||||
binr.ReadByte(); //advance 1 byte
|
||||
else if (twobytes == 0x8203)
|
||||
binr.ReadInt16(); //advance 2 bytes
|
||||
else
|
||||
return null;
|
||||
|
||||
bt = binr.ReadByte();
|
||||
if (bt != 0x00) //expect null byte next
|
||||
return null;
|
||||
|
||||
twobytes = binr.ReadUInt16();
|
||||
if (twobytes == 0x8130
|
||||
) //data read as little endian order (actual data order for Sequence is 30 81)
|
||||
binr.ReadByte(); //advance 1 byte
|
||||
else if (twobytes == 0x8230)
|
||||
binr.ReadInt16(); //advance 2 bytes
|
||||
else
|
||||
return null;
|
||||
|
||||
twobytes = binr.ReadUInt16();
|
||||
byte lowbyte = 0x00;
|
||||
byte highbyte = 0x00;
|
||||
|
||||
if (twobytes == 0x8102
|
||||
) //data read as little endian order (actual data order for Integer is 02 81)
|
||||
lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus
|
||||
else if (twobytes == 0x8202)
|
||||
{
|
||||
highbyte = binr.ReadByte(); //advance 2 bytes
|
||||
lowbyte = binr.ReadByte();
|
||||
}
|
||||
else
|
||||
return null;
|
||||
|
||||
byte[] modint =
|
||||
{lowbyte, highbyte, 0x00, 0x00}; //reverse byte order since asn.1 key uses big endian order
|
||||
int modsize = BitConverter.ToInt32(modint, 0);
|
||||
|
||||
int firstbyte = binr.PeekChar();
|
||||
if (firstbyte == 0x00)
|
||||
{
|
||||
//if first byte (highest order) of modulus is zero, don't include it
|
||||
binr.ReadByte(); //skip this null byte
|
||||
modsize -= 1; //reduce modulus buffer size by 1
|
||||
}
|
||||
|
||||
byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes
|
||||
|
||||
if (binr.ReadByte() != 0x02) //expect an Integer for the exponent data
|
||||
return null;
|
||||
int expbytes =
|
||||
binr
|
||||
.ReadByte(); // should only need one byte for actual exponent data (for all useful values)
|
||||
byte[] exponent = binr.ReadBytes(expbytes);
|
||||
|
||||
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
|
||||
var rsa = RSA.Create();
|
||||
RSAParameters rsaKeyInfo = new RSAParameters
|
||||
{
|
||||
Modulus = modulus,
|
||||
Exponent = exponent
|
||||
};
|
||||
rsa.ImportParameters(rsaKeyInfo);
|
||||
|
||||
return rsa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 导入密钥算法
|
||||
|
||||
private int GetIntegerSize(BinaryReader binr)
|
||||
{
|
||||
byte bt = 0;
|
||||
int count = 0;
|
||||
bt = binr.ReadByte();
|
||||
if (bt != 0x02)
|
||||
return 0;
|
||||
bt = binr.ReadByte();
|
||||
|
||||
if (bt == 0x81)
|
||||
count = binr.ReadByte();
|
||||
else if (bt == 0x82)
|
||||
{
|
||||
var highbyte = binr.ReadByte();
|
||||
var lowbyte = binr.ReadByte();
|
||||
byte[] modint = {lowbyte, highbyte, 0x00, 0x00};
|
||||
count = BitConverter.ToInt32(modint, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
count = bt;
|
||||
}
|
||||
|
||||
while (binr.ReadByte() == 0x00)
|
||||
{
|
||||
count -= 1;
|
||||
}
|
||||
|
||||
binr.BaseStream.Seek(-1, SeekOrigin.Current);
|
||||
return count;
|
||||
}
|
||||
|
||||
private bool CompareBytearrays(byte[] a, byte[] b)
|
||||
{
|
||||
if (a.Length != b.Length)
|
||||
return false;
|
||||
int i = 0;
|
||||
foreach (byte c in a)
|
||||
{
|
||||
if (c != b[i])
|
||||
return false;
|
||||
i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RSA算法类型
|
||||
/// </summary>
|
||||
public enum RsaType
|
||||
{
|
||||
/// <summary>
|
||||
/// SHA1
|
||||
/// </summary>
|
||||
RSA = 0,
|
||||
|
||||
/// <summary>
|
||||
/// RSA2 密钥长度至少为2048
|
||||
/// SHA256
|
||||
/// </summary>
|
||||
RSA2
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class RandomHelper
|
||||
{
|
||||
#region 私有属性
|
||||
|
||||
/// <summary>
|
||||
/// 随机数最小值
|
||||
/// </summary>
|
||||
private static int MiniNum => int.MinValue;
|
||||
|
||||
/// <summary>
|
||||
/// 随机数最大值
|
||||
/// </summary>
|
||||
private static int MaxNum => int.MaxValue;
|
||||
|
||||
/// <summary>
|
||||
/// 随机数长度
|
||||
/// </summary>
|
||||
private static int RandomLength => 4;
|
||||
|
||||
/// <summary>
|
||||
/// 随机数来源
|
||||
/// </summary>
|
||||
private static string RandomString => "0123456789ABCDEFGHIJKMLNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz";
|
||||
|
||||
/// <summary>
|
||||
/// 系统默认生成随机数长度
|
||||
/// </summary>
|
||||
private const int RandomLengthPresent = 6;
|
||||
|
||||
/// <summary>
|
||||
/// 系统默认随机数来源
|
||||
/// </summary>
|
||||
private const string RandomStringPresent = "0123456789ABCDEFGHIJKMLNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz";
|
||||
|
||||
private static readonly Random Random = new Random(DateTime.Now.Millisecond);
|
||||
#endregion
|
||||
|
||||
#region 产生随机字符
|
||||
|
||||
/// <summary>
|
||||
/// 产生随机字符
|
||||
/// </summary>
|
||||
/// <param name="randomLength">产生随机数长度,默认为-1</param>
|
||||
/// <param name="randomString">随机数来源</param>
|
||||
/// <returns></returns>
|
||||
public static string GetRandomString(int randomLength = -1, string randomString = "")
|
||||
{
|
||||
int randomLengthTemp;//随机数长度
|
||||
if (randomLength > 0)
|
||||
randomLengthTemp = randomLength;
|
||||
else if (RandomLength > 0)
|
||||
randomLengthTemp = RandomLength;
|
||||
else
|
||||
randomLengthTemp = RandomLengthPresent;
|
||||
string randomStringTemp;//随机数来源
|
||||
if (!string.IsNullOrEmpty(randomString))
|
||||
randomStringTemp = randomString;
|
||||
else if (!string.IsNullOrEmpty(RandomString))
|
||||
randomStringTemp = RandomString;
|
||||
else
|
||||
randomStringTemp = RandomStringPresent;
|
||||
string returnValue = string.Empty;
|
||||
for (int i = 0; i < randomLengthTemp; i++)
|
||||
{
|
||||
int r = Random.Next(0, randomStringTemp.Length - 1);
|
||||
returnValue += randomStringTemp[r];
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 产生随机数
|
||||
/// <summary>
|
||||
/// 产生随机数
|
||||
/// </summary>
|
||||
/// <param name="minNum">最小随机数</param>
|
||||
/// <param name="maxNum">最大随机数</param>
|
||||
/// <returns></returns>
|
||||
public static int GetRandom(int minNum = -1, int maxNum = -1)
|
||||
{
|
||||
int minNumTemp = minNum == -1 ? MiniNum : minNum;//最小随机数
|
||||
int maxNumTemp = maxNum == -1 ? MaxNum : maxNum;//最大随机数
|
||||
return Random.Next(minNumTemp, maxNumTemp);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 生成一个0.0到1.0的随机小数
|
||||
/// <summary>
|
||||
/// 生成一个0.0到1.0的随机小数
|
||||
/// </summary>
|
||||
public double GetRandomDouble()
|
||||
{
|
||||
return Random.NextDouble();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 对一个数组进行随机排序
|
||||
/// <summary>
|
||||
/// 对一个数组进行随机排序
|
||||
/// </summary>
|
||||
/// <typeparam name="T">数组的类型</typeparam>
|
||||
/// <param name="arr">需要随机排序的数组</param>
|
||||
public void GetRandomArray<T>(T[] arr)
|
||||
{
|
||||
//对数组进行随机排序的算法:随机选择两个位置,将两个位置上的值交换
|
||||
//交换的次数,这里使用数组的长度作为交换次数
|
||||
int count = arr.Length;
|
||||
//开始交换
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
//生成两个随机数位置
|
||||
int randomNum1 = GetRandom(0, arr.Length);
|
||||
int randomNum2 = GetRandom(0, arr.Length);
|
||||
//定义临时变量
|
||||
//交换两个随机数位置的值
|
||||
var temp = arr[randomNum1];
|
||||
arr[randomNum1] = arr[randomNum2];
|
||||
arr[randomNum2] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
public static string Uuid(int len)
|
||||
{
|
||||
len = len > 32 ? 32 : len;
|
||||
var str = Guid.NewGuid().ToString("N");
|
||||
var list = new List<string>();
|
||||
while (true)
|
||||
{
|
||||
var index = GetRandom(0, 32);
|
||||
list.Add(str[index].ToString());
|
||||
if (list.Count >= len)
|
||||
break;
|
||||
}
|
||||
return string.Join("", list);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class RedisLocker
|
||||
{
|
||||
private string _key;
|
||||
private long _lockTime;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key">锁的键</param>
|
||||
/// <param name="outTime">锁超时时间 单位毫秒</param>
|
||||
public RedisLocker(string key,long outTime)
|
||||
{
|
||||
_key =$"Lock:{Assembly.GetCallingAssembly().GetFriendName()}:{key}" ;
|
||||
_lockTime = outTime;
|
||||
}
|
||||
public void Exec(Action action)
|
||||
{
|
||||
if (GetLock())
|
||||
{
|
||||
action();
|
||||
ReleaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
protected bool GetLock()
|
||||
{
|
||||
try
|
||||
{
|
||||
var currentTime = DateTime.Now.GetUnixTimeStamp();
|
||||
if (RedisHelper.SetNx(this._key, currentTime + _lockTime))
|
||||
{
|
||||
Console.WriteLine("获取到Redis锁了");
|
||||
RedisHelper.Expire(_key, TimeSpan.FromMilliseconds(_lockTime)); //设置过期时间
|
||||
return true;
|
||||
}
|
||||
|
||||
//防止SetNx成功但是设置过期时间(Expire)失败造成死锁
|
||||
var lockValue = Convert.ToInt64(RedisHelper.Get(_key));
|
||||
currentTime = DateTime.Now.GetUnixTimeStamp();
|
||||
if (lockValue > 0 && currentTime > lockValue)
|
||||
{
|
||||
var getsetResult = Convert.ToInt64(RedisHelper.GetSet(_key, currentTime));
|
||||
if (getsetResult == 0 || getsetResult == lockValue)
|
||||
{
|
||||
Console.WriteLine("获取到Redis锁了");
|
||||
RedisHelper.Expire(_key, TimeSpan.FromMilliseconds(_lockTime));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Console.WriteLine("没有获取到锁");
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
ReleaseLock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected bool ReleaseLock()
|
||||
{
|
||||
return RedisHelper.Del(_key) > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public static class RegexPattern
|
||||
{
|
||||
public const string Mobile = @"^1[123456789]\d{9}$";//宽松的手机验证。包含运营商可能的新增号段。
|
||||
public const string Email = @"^[\w-]+@[\w-]+\.(com|net|org|edu|mil|tv|biz|info)$";// 邮箱验证
|
||||
public const string IdCard = @"^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$";//18位身份证
|
||||
public const string CarNumber = @"^([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1})$";
|
||||
public static bool IsMatch(string str,string pattern)
|
||||
{
|
||||
return Regex.IsMatch(str, pattern);
|
||||
}
|
||||
public static bool IsMobile(string str)
|
||||
{
|
||||
return IsMatch(str, Mobile);
|
||||
}
|
||||
public static bool IsEmail(string str)
|
||||
{
|
||||
return IsMatch(str, Email);
|
||||
}
|
||||
public static bool IsIdCard(string str)
|
||||
{
|
||||
return IsMatch(str, IdCard);
|
||||
}
|
||||
public static bool IsCarNumber(string str)
|
||||
{
|
||||
return IsMatch(str, CarNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,388 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class SecurityHelper
|
||||
{
|
||||
#region AES加密
|
||||
|
||||
/// <summary>
|
||||
/// AES加密
|
||||
/// </summary>
|
||||
/// <param name="toEncrypt"></param>
|
||||
/// <returns></returns>
|
||||
public static string AESEncrypt(string toEncrypt, string key)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(toEncrypt))
|
||||
return string.Empty;
|
||||
// 256-AES key
|
||||
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
|
||||
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
|
||||
|
||||
RijndaelManaged rDel = new RijndaelManaged();
|
||||
rDel.Key = keyArray;
|
||||
rDel.Mode = CipherMode.ECB;
|
||||
rDel.Padding = PaddingMode.PKCS7;
|
||||
|
||||
ICryptoTransform cTransform = rDel.CreateEncryptor();
|
||||
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
|
||||
|
||||
|
||||
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AES解密
|
||||
|
||||
/// <summary>
|
||||
/// AES解密
|
||||
/// </summary>
|
||||
/// <param name="toDecrypt"></param>
|
||||
/// <returns></returns>
|
||||
public static string Decrypt(string toDecrypt, string key)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(toDecrypt))
|
||||
return string.Empty;
|
||||
try
|
||||
{
|
||||
// 256-AES key
|
||||
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
|
||||
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
|
||||
|
||||
RijndaelManaged rDel = new RijndaelManaged();
|
||||
rDel.Key = keyArray;
|
||||
rDel.Mode = CipherMode.ECB;
|
||||
rDel.Padding = PaddingMode.PKCS7;
|
||||
|
||||
ICryptoTransform cTransform = rDel.CreateDecryptor();
|
||||
|
||||
|
||||
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
|
||||
return UTF8Encoding.UTF8.GetString(resultArray);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
LogHelper.Error("aes Decrypt", ex.Message);
|
||||
return toDecrypt;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MD5加密
|
||||
|
||||
/// <summary>
|
||||
/// MD5加密
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetMd5Hash(string input, Encoding encoding = null)
|
||||
{
|
||||
if (encoding == null)
|
||||
{
|
||||
encoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
|
||||
MD5 myMD5 = new MD5CryptoServiceProvider();
|
||||
byte[] signed = myMD5.ComputeHash(encoding.GetBytes(input));
|
||||
string signResult = byte2mac(signed);
|
||||
return signResult.ToUpper();
|
||||
}
|
||||
|
||||
//MD5加密方法
|
||||
private static string byte2mac(byte[] signed)
|
||||
{
|
||||
StringBuilder EnText = new StringBuilder();
|
||||
foreach (byte Byte in signed)
|
||||
{
|
||||
EnText.AppendFormat("{0:x2}", Byte);
|
||||
}
|
||||
|
||||
return EnText.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 对字符串进行DES加密
|
||||
|
||||
/// <summary>
|
||||
/// 对字符串进行DES加密
|
||||
/// </summary>
|
||||
/// <param name="sourceString">待加密的字符串</param>
|
||||
/// <returns>加密后的BASE64编码的字符串</returns>
|
||||
public static string DesEncrypt(string sourceString, string key, string iv)
|
||||
{
|
||||
byte[] btKey = Encoding.Default.GetBytes(key);
|
||||
byte[] btIV = Encoding.Default.GetBytes(iv);
|
||||
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
byte[] inData = Encoding.Default.GetBytes(sourceString);
|
||||
using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write))
|
||||
{
|
||||
cs.Write(inData, 0, inData.Length);
|
||||
cs.FlushFinalBlock();
|
||||
}
|
||||
|
||||
return Convert.ToBase64String(ms.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 对DES加密后的字符串进行解密
|
||||
|
||||
/// <summary>
|
||||
/// 对DES加密后的字符串进行解密
|
||||
/// </summary>
|
||||
/// <param name="encryptedString">待解密的字符串</param>
|
||||
/// <returns>解密后的字符串</returns>
|
||||
public static string DesDecrypt(string encryptedString, string key, string iv)
|
||||
{
|
||||
byte[] btKey = Encoding.Default.GetBytes(key);
|
||||
byte[] btIV = Encoding.Default.GetBytes(iv);
|
||||
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
byte[] inData = Convert.FromBase64String(encryptedString);
|
||||
using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(btKey, btIV), CryptoStreamMode.Write))
|
||||
{
|
||||
cs.Write(inData, 0, inData.Length);
|
||||
cs.FlushFinalBlock();
|
||||
}
|
||||
|
||||
return Encoding.Default.GetString(ms.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public static string Sha1(string str)
|
||||
{
|
||||
SHA1 sha1 = new SHA1CryptoServiceProvider();
|
||||
|
||||
byte[] bytes_in = Encoding.UTF8.GetBytes(str);
|
||||
byte[] bytes_out = sha1.ComputeHash(bytes_in);
|
||||
sha1.Dispose();
|
||||
|
||||
var sb = new StringBuilder();
|
||||
foreach (byte b in bytes_out)
|
||||
{
|
||||
sb.Append(b.ToString("x2"));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string HMACSHA1(string text, string key)
|
||||
{
|
||||
HMACSHA1 myhmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(key));
|
||||
byte[] byteArray = Encoding.UTF8.GetBytes(text);
|
||||
MemoryStream stream = new MemoryStream(byteArray);
|
||||
string signature = Convert.ToBase64String(myhmacsha1.ComputeHash(stream));
|
||||
|
||||
return signature;
|
||||
}
|
||||
|
||||
#region JS Aes解密
|
||||
|
||||
/// <summary>
|
||||
/// JS Aes解密
|
||||
/// </summary>
|
||||
/// <param name="toDecrypt"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="iv"></param>
|
||||
/// <returns></returns>
|
||||
public static string JsAesDecrypt(string toDecrypt, string key, string iv)
|
||||
{
|
||||
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
|
||||
byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
|
||||
byte[] cipherText = HexToByteArray(toDecrypt);
|
||||
// Check arguments.
|
||||
if (cipherText == null || cipherText.Length <= 0)
|
||||
{
|
||||
throw new ArgumentNullException("cipherText");
|
||||
}
|
||||
|
||||
if (key == null || key.Length <= 0)
|
||||
{
|
||||
throw new ArgumentNullException("key");
|
||||
}
|
||||
|
||||
if (iv == null || iv.Length <= 0)
|
||||
{
|
||||
throw new ArgumentNullException("key");
|
||||
}
|
||||
|
||||
string plaintext = null;
|
||||
using (var rijAlg = new RijndaelManaged())
|
||||
{
|
||||
//Settings
|
||||
rijAlg.Mode = CipherMode.CBC;
|
||||
rijAlg.Padding = PaddingMode.PKCS7;
|
||||
rijAlg.FeedbackSize = 128;
|
||||
|
||||
rijAlg.Key = keyArray;
|
||||
rijAlg.IV = ivArray;
|
||||
|
||||
var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
|
||||
|
||||
using (var msDecrypt = new MemoryStream(cipherText))
|
||||
{
|
||||
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
|
||||
{
|
||||
using (var srDecrypt = new StreamReader(csDecrypt))
|
||||
{
|
||||
plaintext = srDecrypt.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
private static byte[] HexToByteArray(string hex)
|
||||
{
|
||||
int NumberChars = hex.Length;
|
||||
byte[] bytes = new byte[NumberChars / 2];
|
||||
for (int i = 0; i < NumberChars; i += 2)
|
||||
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region JS Aes 加密
|
||||
|
||||
/// <summary>
|
||||
/// JsAesEncrypt
|
||||
/// </summary>
|
||||
/// <param name="plainText"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="iv"></param>
|
||||
/// <returns></returns>
|
||||
public static string JsAesEncrypt(string plainText, string key, string iv)
|
||||
{
|
||||
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
|
||||
byte[] ivArray = UTF8Encoding.UTF8.GetBytes(iv);
|
||||
|
||||
// Check arguments.
|
||||
if (plainText == null || plainText.Length <= 0)
|
||||
{
|
||||
throw new ArgumentNullException("plainText");
|
||||
}
|
||||
|
||||
if (key == null || key.Length <= 0)
|
||||
{
|
||||
throw new ArgumentNullException("key");
|
||||
}
|
||||
|
||||
if (iv == null || iv.Length <= 0)
|
||||
{
|
||||
throw new ArgumentNullException("key");
|
||||
}
|
||||
|
||||
byte[] encrypted;
|
||||
using (var rijAlg = new RijndaelManaged())
|
||||
{
|
||||
rijAlg.Mode = CipherMode.CBC;
|
||||
rijAlg.Padding = PaddingMode.PKCS7;
|
||||
rijAlg.FeedbackSize = 128;
|
||||
|
||||
rijAlg.Key = keyArray;
|
||||
rijAlg.IV = ivArray;
|
||||
|
||||
var encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
|
||||
using (var msEncrypt = new MemoryStream())
|
||||
{
|
||||
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
|
||||
{
|
||||
using (var swEncrypt = new StreamWriter(csEncrypt))
|
||||
{
|
||||
swEncrypt.Write(plainText);
|
||||
}
|
||||
|
||||
encrypted = msEncrypt.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the encrypted bytes from the memory stream.
|
||||
return ByteArrayToHex(encrypted);
|
||||
}
|
||||
|
||||
private static string ByteArrayToHex(byte[] ba)
|
||||
{
|
||||
string hex = BitConverter.ToString(ba);
|
||||
return hex.Replace("-", "");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 加密隐藏信息(将原信息其中一部分数据替换为特殊字符)
|
||||
|
||||
/// <summary>
|
||||
/// 加密隐藏信息(将原信息其中一部分数据替换为特殊字符)
|
||||
/// </summary>
|
||||
/// <param name="param">原参数信息</param>
|
||||
/// <param name="key">更换后的特殊字符</param>
|
||||
/// <param name="index">下标</param>
|
||||
/// <param name="length">位数,-1代表到队尾</param>
|
||||
/// <returns></returns>
|
||||
public static string Encrypt(string param, string key, int index, int length = -1)
|
||||
{
|
||||
if (string.IsNullOrEmpty(param))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
string str = "";
|
||||
if (index > param.Length - 1)
|
||||
{
|
||||
return param;
|
||||
}
|
||||
|
||||
str = param.Substring(0, index);
|
||||
if (length == -1)
|
||||
{
|
||||
length = param.Length - index;
|
||||
}
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
str += key;
|
||||
}
|
||||
|
||||
if (index + length < param.Length)
|
||||
{
|
||||
str += param.Substring(index + length);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将密码使用MD5算法求哈希值
|
||||
/// </summary>
|
||||
/// <param name="password"></param>
|
||||
/// <returns></returns>
|
||||
public static string HashPassword(string password)
|
||||
{
|
||||
using (MD5 md5 = MD5.Create())
|
||||
{
|
||||
byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(password));
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class ShellHelper
|
||||
{
|
||||
public static string Bash(string cmd)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
var escapedArgs = cmd.Replace("\"", "\\\"");
|
||||
|
||||
var process = new Process()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "/bin/bash",
|
||||
Arguments = $"-c \"{escapedArgs}\"",
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
};
|
||||
process.Start();
|
||||
string result = process.StandardOutput.ReadToEnd();
|
||||
process.WaitForExit();
|
||||
return result;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void RedirectOutputBash(string cmd)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
cmd = cmd.Replace("\"", "\\\"");
|
||||
|
||||
Console.WriteLine("执行命令");
|
||||
Console.WriteLine(cmd);
|
||||
|
||||
var process = new Process()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "/bin/bash",
|
||||
Arguments = $"-c \"{cmd}\"",
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
}
|
||||
};
|
||||
|
||||
process.OutputDataReceived += (sender, args) => Console.WriteLine(args.Data);
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
process.WaitForExit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class UrlHelper
|
||||
{
|
||||
#region 设置url参数
|
||||
|
||||
/// <summary>
|
||||
/// 设置url参数
|
||||
/// </summary>
|
||||
/// <param name="paramName"></param>
|
||||
/// <param name="paramValue"></param>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public static string SetUrlParam(string url, string paramName, string paramValue)
|
||||
{
|
||||
paramName = paramName.ToLower();
|
||||
|
||||
string currentUrl = url;
|
||||
|
||||
if (!string.IsNullOrEmpty(paramValue))
|
||||
{
|
||||
paramValue = HttpUtility.UrlEncode(paramValue);
|
||||
}
|
||||
|
||||
if (!currentUrl.Contains("?"))
|
||||
{
|
||||
return currentUrl += "?" + paramName + "=" + paramValue;
|
||||
}
|
||||
|
||||
List<string> paramItems = currentUrl.Split('?')[1].Split('&').ToList();
|
||||
|
||||
string paramItem = paramItems.SingleOrDefault(t => t.ToLower().Split('=')[0] == paramName);
|
||||
|
||||
if (!string.IsNullOrEmpty(paramItem))
|
||||
{
|
||||
return currentUrl.Replace(paramItem, paramName + "=" + paramValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (currentUrl.Contains("?"))
|
||||
{
|
||||
currentUrl += "&";
|
||||
}
|
||||
else
|
||||
{
|
||||
currentUrl += "?";
|
||||
}
|
||||
return currentUrl + paramName + "=" + paramValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static string SetUrlParam(string url, object paramObj)
|
||||
{
|
||||
var type = paramObj.GetType();
|
||||
var properties = type.GetProperties();
|
||||
|
||||
foreach (var property in properties)
|
||||
{
|
||||
string name = property.Name;
|
||||
|
||||
object valueObj = property.GetValue(paramObj, null);
|
||||
|
||||
if (valueObj == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string value = valueObj.ToString();
|
||||
|
||||
url = SetUrlParam(url, name, value);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
public static string ToUrlParam(IDictionary<string, string> kvs)
|
||||
{
|
||||
return string.Join("&", kvs.Select(m => $"{m.Key}={m.Value}"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace Hncore.Infrastructure.Common
|
||||
{
|
||||
public class ValidateCodeHelper
|
||||
{
|
||||
public static string MakeCode(int length = 4)
|
||||
{
|
||||
char[] allCharArray = new char[] { '2', '3', '4', '5', '6', '7', '8', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'W', 'X', 'Y', 'Z' };
|
||||
string randomCode = "";
|
||||
int temp = -1;
|
||||
|
||||
Random rand = new Random();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (temp != -1)
|
||||
{
|
||||
rand = new Random(i * temp * ((int)DateTime.Now.Ticks));
|
||||
}
|
||||
int t = rand.Next(allCharArray.Length);
|
||||
if (temp == t)
|
||||
{
|
||||
return MakeCode(length);
|
||||
}
|
||||
temp = t;
|
||||
randomCode += allCharArray[t];
|
||||
}
|
||||
return randomCode;
|
||||
}
|
||||
public static string MakeNumCode(int length = 4)
|
||||
{
|
||||
char[] allCharArray = new char[] { '1','2', '3', '4', '5', '6', '7', '8','9'};
|
||||
string randomCode = "";
|
||||
int temp = -1;
|
||||
|
||||
Random rand = new Random();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (temp != -1)
|
||||
{
|
||||
rand = new Random(i * temp * ((int)DateTime.Now.Ticks));
|
||||
}
|
||||
int t = rand.Next(allCharArray.Length);
|
||||
if (temp == t)
|
||||
{
|
||||
return MakeNumCode(length);
|
||||
}
|
||||
temp = t;
|
||||
randomCode += allCharArray[t];
|
||||
}
|
||||
return randomCode;
|
||||
}
|
||||
|
||||
public static string MakeCharCode(int length = 4)
|
||||
{
|
||||
char[] allCharArray = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'W', 'X', 'Y', 'Z' };
|
||||
string randomCode = "";
|
||||
int temp = -1;
|
||||
|
||||
Random rand = new Random();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (temp != -1)
|
||||
{
|
||||
rand = new Random(i * temp * ((int)DateTime.Now.Ticks));
|
||||
}
|
||||
int t = rand.Next(allCharArray.Length);
|
||||
if (temp == t)
|
||||
{
|
||||
return MakeCharCode(length);
|
||||
}
|
||||
temp = t;
|
||||
randomCode += allCharArray[t];
|
||||
}
|
||||
return randomCode;
|
||||
}
|
||||
|
||||
public static byte[] GenerateCodeImg(string code)
|
||||
{
|
||||
int Gheight = (int)(code.Length * 15) + 10;
|
||||
|
||||
//gheight为图片宽度,根据字符长度自动更改图片宽度
|
||||
using (var img = new Bitmap(Gheight, 22))
|
||||
{
|
||||
using (var g = Graphics.FromImage(img))
|
||||
{
|
||||
SolidBrush whiteBrush = new SolidBrush(Color.White);
|
||||
g.FillRectangle(whiteBrush, 0, 0, Gheight, 22);
|
||||
int i = 0;
|
||||
foreach (char ch in code.ToCharArray())
|
||||
{
|
||||
g.DrawString(ch.ToString(),
|
||||
new Font("Arial", 13, FontStyle.Italic),
|
||||
new SolidBrush(Color.FromArgb(0, 0, 0)),
|
||||
i * 15,
|
||||
0);
|
||||
i++;
|
||||
}
|
||||
|
||||
//在矩形内绘制字串(字串,字体,画笔颜色,左上x.左上y)
|
||||
System.IO.MemoryStream ms = new System.IO.MemoryStream();
|
||||
img.Save(ms, ImageFormat.Jpeg);
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Hncore.Infrastructure.DDD
|
||||
{
|
||||
public abstract class AggregateRoot<TId> : Entity<TId>, IAggregateRoot<TId>
|
||||
{
|
||||
public AggregateRoot()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Hncore.Infrastructure.DDD
|
||||
{
|
||||
/// <summary>
|
||||
/// 实现模型抽象基类
|
||||
/// </summary>
|
||||
/// <typeparam name="TId">主键数据类型</typeparam>
|
||||
public abstract class Entity<TId> : IEntity<TId>
|
||||
{
|
||||
/// <summary>
|
||||
/// 记录数据库主键ID
|
||||
/// </summary>
|
||||
[JsonProperty("Id")]
|
||||
public virtual TId Id { get; set; }
|
||||
}
|
||||
|
||||
public abstract class EntityWithTime<TId> : Entity<TId>
|
||||
{
|
||||
/// <summary>
|
||||
/// 记录添加(创建)时间
|
||||
/// </summary>
|
||||
public virtual DateTime CreateTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 记录最后更新时间
|
||||
/// </summary>
|
||||
public virtual DateTime UpdateTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 记录软删除标记,0.代表正常,1.代表已删除
|
||||
/// </summary>
|
||||
public virtual int DeleteTag { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public abstract class EntityWithDelete<TId> : Entity<TId>,ISoftDelete
|
||||
{
|
||||
/// <summary>
|
||||
/// 记录软删除标记,0.代表正常,1.代表已删除
|
||||
/// </summary>
|
||||
public virtual int DeleteTag { get; set; } = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Hncore.Infrastructure.DDD
|
||||
{
|
||||
public interface IAggregateRoot<TId> : IEntity<TId>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Hncore.Infrastructure.DDD
|
||||
{
|
||||
public interface IEntity
|
||||
{
|
||||
|
||||
}
|
||||
public interface IEntity<TId>: IEntity
|
||||
{
|
||||
TId Id
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Hncore.Infrastructure.DDD
|
||||
{
|
||||
public interface IQuery<TEntity,TId> where TEntity : IEntity<TId>
|
||||
{
|
||||
TEntity GetOne(Expression<Func<TEntity, bool>> condition);
|
||||
|
||||
Task<TEntity> GetOneAsync(Expression<Func<TEntity, bool>> condition);
|
||||
|
||||
PageData<TEntity> GetList(Expression<Func<TEntity, bool>> condition, int pagesize, int pageindex, bool istotal);
|
||||
|
||||
Task<PageData<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> condition, int pagesize, int pageindex, bool istotal);
|
||||
|
||||
List<TEntity> GetList(Expression<Func<TEntity, bool>> condition);
|
||||
|
||||
Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> condition);
|
||||
|
||||
bool Exists(Expression<Func<TEntity, bool>> condition);
|
||||
|
||||
Task<bool> ExistsAsync(Expression<Func<TEntity, bool>> condition);
|
||||
|
||||
List<TEntity> TopN(Expression<Func<TEntity, bool>> condition, int topN);
|
||||
|
||||
Task<List<TEntity>> TopNAsync(Expression<Func<TEntity, bool>> condition, int topN);
|
||||
|
||||
IQueryable<TEntity> GetListQueryable(Expression<Func<TEntity, bool>> condition);
|
||||
|
||||
IQueryable<TEntity> GetQueryable();
|
||||
|
||||
DbContext DbContext();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Infrastructure.DDD
|
||||
{
|
||||
public interface IRepository<TEntity, TId> where TEntity : IEntity<TId>
|
||||
{
|
||||
TEntity FindById(TId id);
|
||||
|
||||
Task<TEntity> FindByIdAsync(TId id);
|
||||
|
||||
void Add(TEntity entity);
|
||||
|
||||
Task AddAsync(TEntity entity);
|
||||
/// <summary>
|
||||
/// 批量添加
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
void AddRange(List<TEntity> entity);
|
||||
/// <summary>
|
||||
/// 批量添加
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
Task AddRangeAsync(List<TEntity> entity);
|
||||
/// <summary>
|
||||
/// 批量修改
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
void UpdateRange(List<TEntity> entity);
|
||||
/// <summary>
|
||||
/// 批量删除
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
void RemoveRange(List<TEntity> entity);
|
||||
|
||||
void Remove(TEntity entity);
|
||||
void Update(TEntity entity);
|
||||
|
||||
|
||||
IQueryable<TEntity> GetQueryable();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Hncore.Infrastructure.DDD
|
||||
{
|
||||
public interface ISoftDelete
|
||||
{
|
||||
int DeleteTag { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Hncore.Infrastructure.DDD
|
||||
{
|
||||
public interface ITenant
|
||||
{
|
||||
int TenantId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Hncore.Infrastructure.DDD
|
||||
{
|
||||
public interface ITenantStore
|
||||
{
|
||||
int StoreId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using Hncore.Infrastructure.WebApi;
|
||||
|
||||
namespace Hncore.Infrastructure.Data
|
||||
{
|
||||
public class BusinessException : Exception
|
||||
{
|
||||
public ResultCode Code { get; } = ResultCode.C_UNKNOWN_ERROR;
|
||||
|
||||
public BusinessException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public BusinessException(ResultCode code, string message = "") : base(message)
|
||||
{
|
||||
Code = code;
|
||||
}
|
||||
|
||||
public static void Throw(string message = "")
|
||||
{
|
||||
throw new BusinessException(message);
|
||||
}
|
||||
|
||||
public static void Throw(ResultCode code, string message = "")
|
||||
{
|
||||
throw new BusinessException(code, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace Hncore.Infrastructure.Data
|
||||
{
|
||||
public class HttpException: Exception
|
||||
{
|
||||
public HttpStatusCode HttpStatusCode { get; set; }
|
||||
|
||||
public string Content { get; set; }
|
||||
|
||||
public HttpException(HttpStatusCode httpStatusCode)
|
||||
{
|
||||
HttpStatusCode = httpStatusCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Hncore.Infrastructure.Data
|
||||
{
|
||||
public interface IPageData
|
||||
{
|
||||
/// <summary>
|
||||
/// 总行数
|
||||
/// </summary>
|
||||
int RowCount { get; set; }
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 分页数据集合
|
||||
/// </summary>
|
||||
public class PageData<T>
|
||||
{
|
||||
public PageData()
|
||||
{
|
||||
List = new List<T>();
|
||||
}
|
||||
|
||||
public PageData(int rowCount, List<T> data)
|
||||
{
|
||||
this.RowCount = rowCount;
|
||||
this.List = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 总行数
|
||||
/// </summary>
|
||||
public int RowCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前页数据集合
|
||||
/// </summary>
|
||||
public List<T> List { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace Hncore.Infrastructure.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// 分页数据源
|
||||
/// </summary>
|
||||
public class PageQueryable<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 总页数
|
||||
/// </summary>
|
||||
public int RowCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前页数据集合
|
||||
/// </summary>
|
||||
public IQueryable<T> Data { get; set; }
|
||||
|
||||
public PageData<T> ToList()
|
||||
{
|
||||
return new PageData<T>(){List=Data.ToList(),RowCount=RowCount};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
namespace Hncore.Infrastructure.Data
|
||||
{
|
||||
public class ResultMessage
|
||||
{
|
||||
public ResultMessage()
|
||||
{
|
||||
Success = true;
|
||||
}
|
||||
|
||||
public string Message { get; set; } = "";
|
||||
|
||||
public bool Success { get; set; }
|
||||
|
||||
public string Code { get; set; } = "";
|
||||
|
||||
public Action CallBack { get; set; } = null;
|
||||
|
||||
public object Data { get; set; } = null;
|
||||
|
||||
public ResultMessage(bool success, string message)
|
||||
{
|
||||
this.Success = success;
|
||||
this.Message = message;
|
||||
}
|
||||
|
||||
public ResultMessage(bool success, string message,object data)
|
||||
{
|
||||
this.Success = success;
|
||||
this.Message = message;
|
||||
this.Data = data;
|
||||
}
|
||||
|
||||
public ResultMessage(bool success)
|
||||
{
|
||||
this.Success = success;
|
||||
}
|
||||
|
||||
public ResultMessage(string message)
|
||||
{
|
||||
Success = true;
|
||||
this.Message = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Hncore.Infrastructure.Data
|
||||
{
|
||||
public class TransactionsHelper
|
||||
{
|
||||
public static void NoLockInvokeDB(Action action)
|
||||
{
|
||||
var transactionOptions = new System.Transactions.TransactionOptions();
|
||||
transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted;
|
||||
using (var transactionScope = new System.Transactions.TransactionScope(System.Transactions.TransactionScopeOption.Required, transactionOptions))
|
||||
{
|
||||
try
|
||||
{
|
||||
action();
|
||||
}
|
||||
finally
|
||||
{
|
||||
transactionScope.Complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.DDD;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Infrastructure.WebApi;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
|
||||
namespace Hncore.Infrastructure.EF
|
||||
{
|
||||
/// <summary>
|
||||
/// 上下文构造器的基类
|
||||
/// </summary>
|
||||
public class DbContextBase : DbContext
|
||||
{
|
||||
private IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
private bool _enabledLog = false;
|
||||
|
||||
private int _tenantid = 0;
|
||||
|
||||
private int _storeId = 0;
|
||||
|
||||
private bool _root = false;
|
||||
|
||||
private bool _allow = false;
|
||||
|
||||
public DbContextBase(DbContextOptions options, IHttpContextAccessor httpContextAccessor) : base(options)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
|
||||
if (UseTenantFilter())
|
||||
{
|
||||
ManageUserInfo manageUserInfo = _httpContextAccessor.HttpContext.Request.GetManageUserInfo();
|
||||
|
||||
if (manageUserInfo != null)
|
||||
{
|
||||
_tenantid = manageUserInfo.TenantId;
|
||||
_storeId = manageUserInfo.StoreId;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_allow = true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool UseTenantFilter()
|
||||
{
|
||||
if (_httpContextAccessor == null || _httpContextAccessor.HttpContext == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _httpContextAccessor.HttpContext.Items.ContainsKey("AuthPassedFilterName")
|
||||
&& _httpContextAccessor.HttpContext.Items["AuthPassedFilterName"].ToString() == "ManageAuth";
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// model构造器 创建实体映射
|
||||
/// </summary>
|
||||
/// <param name="modelBuilder"></param>
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
if (!EnvironmentVariableHelper.IsAspNetCoreProduction)
|
||||
{
|
||||
LogHelper.Debug("进入DbContextBase的OnModelCreating函数",
|
||||
$"UseGlobalManageAuthFilter:{GlobalData.UseGlobalManageAuthFilter}\ntoken:{_httpContextAccessor?.HttpContext?.Request?.GetManageUserInfo()?.ToJson(true)}");
|
||||
}
|
||||
|
||||
foreach (var type in modelBuilder.Model.GetEntityTypes())
|
||||
{
|
||||
if (typeof(ISoftDelete).IsAssignableFrom(type.ClrType))
|
||||
{
|
||||
modelBuilder.Entity(type.ClrType).AddQueryFilter<ISoftDelete>(t => t.DeleteTag == 0);
|
||||
}
|
||||
//if (typeof(ITenant).IsAssignableFrom(type.ClrType))
|
||||
//{
|
||||
// modelBuilder.Entity(type.ClrType).AddQueryFilter<ITenant>(t => _allow || t.TenantId == _tenantid);
|
||||
//}
|
||||
|
||||
//if (typeof(ITenantStore).IsAssignableFrom(type.ClrType))
|
||||
//{
|
||||
// modelBuilder.Entity(type.ClrType)
|
||||
// .AddQueryFilter<ITenantStore>(t => _storeId == 0|| t.StoreId==_storeId);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
if (_httpContextAccessor?.HttpContext?.Request?.Headers != null)
|
||||
{
|
||||
if (_httpContextAccessor.HttpContext.Request.Headers.ContainsKey("enable-ef-log"))
|
||||
{
|
||||
if (_httpContextAccessor.HttpContext.Request.Headers.ContainsKey("enable-ef-log").ToBool())
|
||||
{
|
||||
if (_enabledLog == false)
|
||||
{
|
||||
optionsBuilder.EnableDebugTrace(_httpContextAccessor);
|
||||
_enabledLog = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#if DEBUG
|
||||
Console.WriteLine("当前为debug模式,开启EF DebugTrace");
|
||||
optionsBuilder.EnableDebugTrace(null);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
/// <summary>
|
||||
/// EF上下文对象扩展类
|
||||
/// </summary>
|
||||
///
|
||||
public static class DbContextExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行SQL返回受影响的行数
|
||||
/// </summary>
|
||||
public static int ExecSqlNoQuery(this DbContext db, string sql, DbParameter[] sqlParams = null)
|
||||
{
|
||||
return ExecuteNoQuery(db, sql, sqlParams);
|
||||
}
|
||||
/// <summary>
|
||||
/// 执行存储过程返回IEnumerable数据集
|
||||
/// </summary>
|
||||
public static IEnumerable<T> ExecProcQuery<T>(this DbContext db, string sql, DbParameter[] sqlParams = null) where T : new()
|
||||
{
|
||||
return Execute<T>(db, sql, CommandType.StoredProcedure, sqlParams);
|
||||
}
|
||||
/// <summary>
|
||||
/// 执行存储过程返回IEnumerable数据集
|
||||
/// </summary>
|
||||
public static DataSet ExecProcDataSet(this DbContext db, string sql, DbParameter[] sqlParams = null)
|
||||
{
|
||||
return ExecuteDataSet(db, sql, CommandType.StoredProcedure, sqlParams);
|
||||
}
|
||||
/// <summary>
|
||||
/// 执行sql返回IEnumerable数据集
|
||||
/// </summary>
|
||||
public static IEnumerable<T> ExecSqlQuery<T>(this DbContext db, string sql, DbParameter[] sqlParams = null) where T : new()
|
||||
{
|
||||
return Execute<T>(db, sql, CommandType.Text, sqlParams);
|
||||
}
|
||||
/// <summary>
|
||||
/// 执行SQL并返回受影响的行数
|
||||
/// </summary>
|
||||
/// <param name="db"></param>
|
||||
/// <param name="sql"></param>
|
||||
/// <param name="sqlParams"></param>
|
||||
/// <returns></returns>
|
||||
private static int ExecuteNoQuery(this DbContext db, string sql, DbParameter[] sqlParams)
|
||||
{
|
||||
DbConnection connection = db.Database.GetDbConnection();
|
||||
DbCommand cmd = connection.CreateCommand();
|
||||
int result = 0;
|
||||
db.Database.OpenConnection();
|
||||
cmd.CommandText = sql;
|
||||
cmd.CommandType = CommandType.Text;
|
||||
if (sqlParams != null)
|
||||
{
|
||||
cmd.Parameters.AddRange(sqlParams);
|
||||
}
|
||||
result = cmd.ExecuteNonQuery();
|
||||
db.Database.CloseConnection();
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// 执行SQL,返回查询结果
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="db"></param>
|
||||
/// <param name="sql"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="sqlParams"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<T> Execute<T>(this DbContext db, string sql, CommandType type, DbParameter[] sqlParams) where T : new()
|
||||
{
|
||||
DbConnection connection = db.Database.GetDbConnection();
|
||||
DbCommand cmd = connection.CreateCommand();
|
||||
DataTable dt = new DataTable();
|
||||
try
|
||||
{
|
||||
db.Database.OpenConnection();
|
||||
cmd.CommandText = sql;
|
||||
cmd.CommandType = type;
|
||||
if (sqlParams != null)
|
||||
{
|
||||
cmd.Parameters.AddRange(sqlParams);
|
||||
}
|
||||
using (DbDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
dt.Load(reader);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
db.Database.CloseConnection();
|
||||
}
|
||||
return dt.ToCollection<T>();
|
||||
}
|
||||
/// <summary>
|
||||
/// 执行SQL,返回查询结果
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="db"></param>
|
||||
/// <param name="sql"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="sqlParams"></param>
|
||||
/// <returns></returns>
|
||||
private static DataSet ExecuteDataSet(this DbContext db, string sql, CommandType type, DbParameter[] sqlParams)
|
||||
{
|
||||
DbConnection connection = db.Database.GetDbConnection();
|
||||
DbCommand cmd = connection.CreateCommand();
|
||||
db.Database.OpenConnection();
|
||||
cmd.CommandText = sql;
|
||||
cmd.CommandType = type;
|
||||
if (sqlParams != null)
|
||||
{
|
||||
cmd.Parameters.AddRange(sqlParams);
|
||||
}
|
||||
DataSet ds = new DataSet();
|
||||
using (DbDataReader reader = cmd.ExecuteReader())
|
||||
{
|
||||
ds.Load(reader,LoadOption.PreserveChanges,"data","info");
|
||||
}
|
||||
db.Database.CloseConnection();
|
||||
return ds;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DataTable扩展类
|
||||
/// </summary>
|
||||
///
|
||||
public static class ExtendDataTable
|
||||
{
|
||||
/// <summary>
|
||||
/// 将对象转换成DataTable
|
||||
/// </summary>
|
||||
/// <typeparam name="T">源对象类型</typeparam>
|
||||
/// <param name="data">源对象列表</param>
|
||||
/// <returns>转换后的DataTable</returns>
|
||||
///
|
||||
public static DataTable ToDataTable<T>(this IEnumerable<T> data)
|
||||
{
|
||||
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
|
||||
var table = new DataTable();
|
||||
foreach (PropertyDescriptor prop in properties)
|
||||
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
|
||||
foreach (T item in data)
|
||||
{
|
||||
DataRow row = table.NewRow();
|
||||
foreach (PropertyDescriptor prop in properties)
|
||||
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
|
||||
table.Rows.Add(row);
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将DataTable首行转换成目标对象
|
||||
/// </summary>
|
||||
/// <typeparam name="T">目标对象类型</typeparam>
|
||||
/// <param name="dt">源DataTable对象</param>
|
||||
/// <returns>转换后的目标对象</returns>
|
||||
///
|
||||
public static T ToEntity<T>(this DataTable dt) where T : new()
|
||||
{
|
||||
IEnumerable<T> entities = dt.ToCollection<T>();
|
||||
return entities.FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将DataTable转换成目标对象列表
|
||||
/// </summary>
|
||||
/// <typeparam name="T">目标对象类型</typeparam>
|
||||
/// <param name="dt">源DataTable对象</param>
|
||||
/// <returns>转换后的目标对象列表</returns>
|
||||
///
|
||||
public static IEnumerable<T> ToCollection<T>(this DataTable dt) where T : new()
|
||||
{
|
||||
if (dt == null || dt.Rows.Count == 0)
|
||||
{
|
||||
return Enumerable.Empty<T>();
|
||||
}
|
||||
IList<T> ts = new List<T>();
|
||||
// 获得此模型的类型
|
||||
Type type = typeof(T);
|
||||
string tempName = string.Empty;
|
||||
foreach (DataRow dr in dt.Rows)
|
||||
{
|
||||
T t = new T();
|
||||
PropertyInfo[] propertys = t.GetType().GetProperties();
|
||||
foreach (PropertyInfo pi in propertys)
|
||||
{
|
||||
tempName = pi.Name;
|
||||
//检查DataTable是否包含此列(列名==对象的属性名)
|
||||
if (dt.Columns.Contains(tempName))
|
||||
{
|
||||
// 判断此属性是否有Setter
|
||||
if (!pi.CanWrite) continue;//该属性不可写,直接跳出
|
||||
object value = dr[tempName];
|
||||
if (value != DBNull.Value)
|
||||
{
|
||||
if (!pi.PropertyType.IsGenericType)
|
||||
{
|
||||
value = Convert.ChangeType(value, pi.PropertyType);
|
||||
pi.SetValue(t, value);
|
||||
}
|
||||
else {
|
||||
Type genericTypeDefinition = pi.PropertyType.GetGenericTypeDefinition();
|
||||
if (genericTypeDefinition == typeof(Nullable<>))
|
||||
{
|
||||
value = Convert.ChangeType(value, Nullable.GetUnderlyingType(pi.PropertyType));
|
||||
pi.SetValue(t, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ts.Add(t);
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.DDD;
|
||||
using Hncore.Infrastructure.EntitiesExtension;
|
||||
|
||||
namespace Hncore.Infrastructure.EF
|
||||
{
|
||||
public static class DbSetExtension
|
||||
{
|
||||
public static TEntity GetOne<TEntity>(this DbSet<TEntity> dbSet, Expression<Func<TEntity, bool>> exp)
|
||||
where TEntity : class
|
||||
{
|
||||
return dbSet.AsNoTracking().FirstOrDefault(exp);
|
||||
}
|
||||
|
||||
public static Task<TEntity> GetOneAsync<TEntity>(this DbSet<TEntity> dbSet,
|
||||
Expression<Func<TEntity, bool>> exp) where TEntity : class
|
||||
{
|
||||
return dbSet.AsNoTracking().FirstOrDefaultAsync(exp);
|
||||
}
|
||||
|
||||
public static PageData<TEntity> GetList<TEntity, TId>(this DbSet<TEntity> dbSet,
|
||||
Expression<Func<TEntity, bool>> exp, int pagesize, int pageindex, bool istotal)
|
||||
where TEntity : class, IEntity<TId>
|
||||
{
|
||||
return dbSet.AsNoTracking()
|
||||
.Where(exp)
|
||||
.OrderByDescending(t => t.Id)
|
||||
.ListPager(pagesize, pageindex, istotal);
|
||||
}
|
||||
|
||||
public static Task<PageData<TEntity>> GetListAsync<TEntity>(this DbSet<TEntity> dbSet,
|
||||
Expression<Func<TEntity, bool>> exp, int pagesize, int pageindex, bool istotal)
|
||||
where TEntity : class
|
||||
{
|
||||
return dbSet.AsNoTracking()
|
||||
.Where(exp)
|
||||
.ListPagerAsync(pagesize, pageindex, istotal);
|
||||
}
|
||||
|
||||
public static List<TEntity> GetList<TEntity>(this DbSet<TEntity> dbSet, Expression<Func<TEntity, bool>> exp)
|
||||
where TEntity : class, IEntity
|
||||
{
|
||||
return dbSet.AsNoTracking()
|
||||
.Where(exp)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static Task<List<TEntity>> GetListAsync<TEntity>(this DbSet<TEntity> dbSet,
|
||||
Expression<Func<TEntity, bool>> exp)
|
||||
where TEntity : class, IEntity
|
||||
{
|
||||
return dbSet.AsNoTracking()
|
||||
.Where(exp)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public static IQueryable<TEntity> GetListQueryable<TEntity>(this DbSet<TEntity> dbSet,
|
||||
Expression<Func<TEntity, bool>> exp)
|
||||
where TEntity : class, IEntity
|
||||
{
|
||||
return dbSet.AsNoTracking()
|
||||
.Where(exp);
|
||||
}
|
||||
|
||||
public static bool Exists<TEntity>(this DbSet<TEntity> dbSet, Expression<Func<TEntity, bool>> exp)
|
||||
where TEntity : class, IEntity
|
||||
{
|
||||
return dbSet.AsNoTracking()
|
||||
.Any(exp);
|
||||
}
|
||||
|
||||
public static Task<bool> ExistsAsync<TEntity>(this DbSet<TEntity> dbSet,
|
||||
Expression<Func<TEntity, bool>> exp)
|
||||
where TEntity : class, IEntity
|
||||
{
|
||||
return dbSet.AsNoTracking()
|
||||
.AnyAsync(exp);
|
||||
}
|
||||
|
||||
public static List<TEntity> TopN<TEntity>(this DbSet<TEntity> dbSet,
|
||||
Expression<Func<TEntity, bool>> condition, int topN)
|
||||
where TEntity : class, IEntity
|
||||
{
|
||||
return dbSet.AsNoTracking()
|
||||
.Where(condition)
|
||||
.TopN(topN)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static Task<List<TEntity>> TopNAsync<TEntity>(this DbSet<TEntity> dbSet,
|
||||
Expression<Func<TEntity, bool>> condition, int topN)
|
||||
where TEntity : class, IEntity
|
||||
{
|
||||
return dbSet.AsNoTracking()
|
||||
.Where(condition)
|
||||
.TopN(topN)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public static IQueryable<TEntity> GetQueryable<TEntity>(this DbSet<TEntity> dbSet) where TEntity : class
|
||||
{
|
||||
return dbSet.AsNoTracking();
|
||||
}
|
||||
|
||||
public static TEntity FindById<TEntity>(this DbSet<TEntity> dbSet,object id) where TEntity : class
|
||||
{
|
||||
return dbSet.Find(id);
|
||||
}
|
||||
|
||||
public static Task<TEntity> FindByIdAsync<TEntity>(this DbSet<TEntity> dbSet, object id) where TEntity : class
|
||||
{
|
||||
return dbSet.FindAsync(id);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace Hncore.Infrastructure.EF
|
||||
{
|
||||
public interface IEntityMap
|
||||
{
|
||||
void Map(ModelBuilder builder);
|
||||
}
|
||||
|
||||
public interface IEntityMap<TEntityType> : IEntityMap where TEntityType : class
|
||||
{
|
||||
void Map(EntityTypeBuilder<TEntityType> builder);
|
||||
}
|
||||
|
||||
public abstract class EntityMapBase<T> : IEntityMap<T> where T : class
|
||||
{
|
||||
public abstract void Map(EntityTypeBuilder<T> builder);
|
||||
|
||||
public void Map(ModelBuilder builder)
|
||||
{
|
||||
Map(builder.Entity<T>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Hncore.Infrastructure.EF
|
||||
{
|
||||
public static class AutoMapExtensions
|
||||
{
|
||||
private static object syncRoot = new object();
|
||||
private static ConcurrentDictionary<IEntityMap, object> maps;
|
||||
|
||||
public static void AutoMap(this ModelBuilder modelBuilder, Type assType)
|
||||
{
|
||||
if (maps == null)
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
if (maps == null)
|
||||
{
|
||||
maps = new ConcurrentDictionary<IEntityMap, object>();
|
||||
|
||||
Type mappingInterface = typeof(IEntityMap<>);
|
||||
|
||||
var mappingTypes = assType.GetTypeInfo().Assembly.GetTypes()
|
||||
.Where(x => !x.IsAbstract
|
||||
&& x.GetInterfaces().Any(y => y.GetTypeInfo().IsGenericType
|
||||
&& y.GetGenericTypeDefinition() ==
|
||||
mappingInterface));
|
||||
|
||||
foreach (var map in mappingTypes.Select(Activator.CreateInstance).Cast<IEntityMap>())
|
||||
{
|
||||
maps.TryAdd(map, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var map in maps.Keys)
|
||||
{
|
||||
map.Map(modelBuilder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Hncore.Infrastructure.Core.Web;
|
||||
|
||||
namespace Hncore.Infrastructure.EF
|
||||
{
|
||||
public class TraceLogger : ILogger
|
||||
{
|
||||
private readonly string categoryName;
|
||||
private IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public TraceLogger(string categoryName, IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
this.categoryName = categoryName;
|
||||
this._httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel) => true;
|
||||
|
||||
public void Log<TState>(
|
||||
LogLevel logLevel,
|
||||
EventId eventId,
|
||||
TState state,
|
||||
Exception exception,
|
||||
Func<TState, Exception, string> formatter)
|
||||
{
|
||||
if (logLevel == LogLevel.Information && categoryName == "Microsoft.EntityFrameworkCore.Database.Command")
|
||||
{
|
||||
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 执行sql:");
|
||||
|
||||
if (exception != null)
|
||||
{
|
||||
Console.WriteLine("发生异常:\n" + exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state.GetType().Name == "LogValues`6")
|
||||
{
|
||||
var paramText = state.GetType().GetField("_value1").GetValue(state).ToString();
|
||||
var sql = state.GetType().GetField("_value5").GetValue(state).ToString();
|
||||
|
||||
var paramList = paramText.RegexMatches("@__.*?='.*?'");
|
||||
|
||||
paramList.ForEach(param =>
|
||||
{
|
||||
var arr = param.Split('=');
|
||||
|
||||
sql = sql.Replace(arr[0], arr[1]);
|
||||
});
|
||||
|
||||
Console.WriteLine(sql);
|
||||
|
||||
if (_httpContextAccessor?.HttpContext?.Request?.Headers != null
|
||||
&& _httpContextAccessor.HttpContext.Request.Headers
|
||||
.ContainsKey("enable-ef-log").ToBool())
|
||||
{
|
||||
StringBuilder log = new StringBuilder();
|
||||
|
||||
log.Append("请求URL:" + _httpContextAccessor.HttpContext.Request.GetAbsoluteUri() + "");
|
||||
log.Append("\nMethod:" + _httpContextAccessor.HttpContext.Request.Method + "\n");
|
||||
if (_httpContextAccessor.HttpContext.Request.Method.ToLower() != "get")
|
||||
{
|
||||
log.Append("Body:\n" + _httpContextAccessor.HttpContext.Items["___requestbody"] +
|
||||
"\n------------------------\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.Append("\n------------------------\n");
|
||||
}
|
||||
|
||||
log.Append(sql);
|
||||
|
||||
LogHelper.Debug("efcore日志", log.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} {logLevel} {eventId.Id} {this.categoryName}");
|
||||
//Console.WriteLine(formatter(state, exception));
|
||||
}
|
||||
}
|
||||
|
||||
public IDisposable BeginScope<TState>(TState state) => null;
|
||||
}
|
||||
|
||||
public class TraceLoggerProvider : ILoggerProvider
|
||||
{
|
||||
private IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public TraceLoggerProvider(IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
public ILogger CreateLogger(string categoryName) => new TraceLogger(categoryName, _httpContextAccessor);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class DebugLog
|
||||
{
|
||||
public static void EnableDebugTrace(this DbContextOptionsBuilder optionsBuilder,
|
||||
IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
LoggerFactory loggerFactory = new LoggerFactory();
|
||||
loggerFactory.AddProvider(new TraceLoggerProvider(httpContextAccessor));
|
||||
optionsBuilder.UseLoggerFactory(loggerFactory);
|
||||
optionsBuilder.EnableSensitiveDataLogging();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.DDD;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Hncore.Infrastructure.WebApi;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
using Remotion.Linq.Parsing.ExpressionVisitors;
|
||||
using Hncore.Infrastructure.Core.Web;
|
||||
|
||||
namespace Hncore.Infrastructure.EF
|
||||
{
|
||||
public static class QueryFilterExtensions
|
||||
{
|
||||
public static void AddQueryFilter<T>(this EntityTypeBuilder entityTypeBuilder,
|
||||
Expression<Func<T, bool>> expression)
|
||||
{
|
||||
var parameterType = Expression.Parameter(entityTypeBuilder.Metadata.ClrType);
|
||||
var expressionFilter = ReplacingExpressionVisitor.Replace(
|
||||
expression.Parameters.Single(), parameterType, expression.Body);
|
||||
|
||||
var internalEntityTypeBuilder = entityTypeBuilder.GetInternalEntityTypeBuilder();
|
||||
if (internalEntityTypeBuilder.Metadata.QueryFilter != null)
|
||||
{
|
||||
var currentQueryFilter = internalEntityTypeBuilder.Metadata.QueryFilter;
|
||||
var currentExpressionFilter = ReplacingExpressionVisitor.Replace(
|
||||
currentQueryFilter.Parameters.Single(), parameterType, currentQueryFilter.Body);
|
||||
expressionFilter = Expression.AndAlso(currentExpressionFilter, expressionFilter);
|
||||
}
|
||||
|
||||
var lambdaExpression = Expression.Lambda(expressionFilter, parameterType);
|
||||
entityTypeBuilder.HasQueryFilter(lambdaExpression);
|
||||
}
|
||||
|
||||
internal static InternalEntityTypeBuilder GetInternalEntityTypeBuilder(this EntityTypeBuilder entityTypeBuilder)
|
||||
{
|
||||
var internalEntityTypeBuilder = typeof(EntityTypeBuilder)
|
||||
.GetProperty("Builder", BindingFlags.NonPublic | BindingFlags.Instance)?
|
||||
.GetValue(entityTypeBuilder) as InternalEntityTypeBuilder;
|
||||
|
||||
return internalEntityTypeBuilder;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,196 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Hncore.Infrastructure.EF
|
||||
{
|
||||
public static class Sql
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行Reader
|
||||
/// </summary>
|
||||
/// <param name="dbContext"></param>
|
||||
/// <param name="sql"></param>
|
||||
/// <param name="action"></param>
|
||||
public static void Reader(this DbContext dbContext, string sql, Action<DbDataReader> action)
|
||||
{
|
||||
var conn = dbContext.Database.GetDbConnection();
|
||||
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
using (var command = conn.CreateCommand())
|
||||
{
|
||||
string query = sql;
|
||||
|
||||
command.CommandText = query;
|
||||
|
||||
using (DbDataReader reader = command.ExecuteReader())
|
||||
{
|
||||
if (reader.HasRows)
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
action(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行Query
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="dbContext"></param>
|
||||
/// <param name="sql"></param>
|
||||
/// <returns></returns>
|
||||
public static List<T> SqlQuery<T>(this DbContext dbContext, string sql)
|
||||
{
|
||||
List<T> list = new List<T>();
|
||||
|
||||
var conn = dbContext.Database.GetDbConnection();
|
||||
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
using (var command = conn.CreateCommand())
|
||||
{
|
||||
string query = sql;
|
||||
|
||||
command.CommandText = query;
|
||||
|
||||
using (DbDataReader reader = command.ExecuteReader())
|
||||
{
|
||||
if (reader.HasRows)
|
||||
{
|
||||
list = reader.ReaderToList<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Close();
|
||||
}
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行Sql命令
|
||||
/// </summary>
|
||||
/// <param name="dbContext"></param>
|
||||
/// <param name="sql"></param>
|
||||
/// <returns></returns>
|
||||
public static int ExecuteSql(this DbContext dbContext, string sql)
|
||||
{
|
||||
var conn = dbContext.Database.GetDbConnection();
|
||||
int rowAffected = 0;
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
|
||||
using (var command = conn.CreateCommand())
|
||||
{
|
||||
command.CommandText = sql;
|
||||
rowAffected = command.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Close();
|
||||
}
|
||||
|
||||
return rowAffected;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DataReader转泛型
|
||||
/// </summary>
|
||||
/// <typeparam name="T">传入的实体类</typeparam>
|
||||
/// <param name="objReader">DataReader对象</param>
|
||||
/// <returns></returns>
|
||||
public static List<T> ReaderToList<T>(this DbDataReader objReader)
|
||||
{
|
||||
using (objReader)
|
||||
{
|
||||
List<T> list = new List<T>();
|
||||
|
||||
//获取传入的数据类型
|
||||
Type modelType = typeof(T);
|
||||
|
||||
//遍历DataReader对象
|
||||
while (objReader.Read())
|
||||
{
|
||||
//使用与指定参数匹配最高的构造函数,来创建指定类型的实例
|
||||
T model = Activator.CreateInstance<T>();
|
||||
for (int i = 0; i < objReader.FieldCount; i++)
|
||||
{
|
||||
//判断字段值是否为空或不存在的值
|
||||
if (!IsNullOrDBNull(objReader[i]))
|
||||
{
|
||||
//匹配字段名
|
||||
PropertyInfo pi = modelType.GetProperty(objReader.GetName(i),
|
||||
BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance |
|
||||
BindingFlags.IgnoreCase);
|
||||
if (pi != null)
|
||||
{
|
||||
//绑定实体对象中同名的字段
|
||||
pi.SetValue(model, CheckType(objReader[i], pi.PropertyType), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list.Add(model);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断指定对象是否是有效值
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
private static bool IsNullOrDBNull(object obj)
|
||||
{
|
||||
return (obj == null || (obj is DBNull)) ? true : false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对可空类型进行判断转换
|
||||
/// </summary>
|
||||
/// <param name="value">DataReader字段的值</param>
|
||||
/// <param name="conversionType">该字段的类型</param>
|
||||
/// <returns></returns>
|
||||
private static object CheckType(object value, Type conversionType)
|
||||
{
|
||||
if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
|
||||
{
|
||||
if (value == null)
|
||||
return null;
|
||||
System.ComponentModel.NullableConverter nullableConverter =
|
||||
new System.ComponentModel.NullableConverter(conversionType);
|
||||
conversionType = nullableConverter.UnderlyingType;
|
||||
}
|
||||
|
||||
if (typeof(System.Enum).IsAssignableFrom(conversionType))
|
||||
{
|
||||
return Enum.Parse(conversionType, value.ToString());
|
||||
}
|
||||
return Convert.ChangeType(value, conversionType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Hncore.Infrastructure.EF
|
||||
{
|
||||
public interface IQueryDbContext
|
||||
{
|
||||
DbContext DbContext { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Hncore.Infrastructure.EF
|
||||
{
|
||||
public interface IRepositoryDbContext
|
||||
{
|
||||
DbContext DbContext { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.DDD;
|
||||
|
||||
|
||||
namespace Hncore.Infrastructure.EF
|
||||
{
|
||||
public class QueryBase<TEntity, TId> : IQuery<TEntity, TId> where TEntity : class, IEntity<TId>
|
||||
{
|
||||
protected DbContext Dbcontext;
|
||||
|
||||
public QueryBase(IQueryDbContext dbContext)
|
||||
{
|
||||
Dbcontext = dbContext.DbContext;
|
||||
}
|
||||
|
||||
public TEntity GetOne(Expression<Func<TEntity, bool>> condition)
|
||||
{
|
||||
return Dbcontext.GetOne<TEntity, TId>(condition);
|
||||
}
|
||||
|
||||
public Task<TEntity> GetOneAsync(Expression<Func<TEntity, bool>> condition)
|
||||
{
|
||||
return Dbcontext.GetOneAsync<TEntity, TId>(condition);
|
||||
}
|
||||
|
||||
public PageData<TEntity> GetList(Expression<Func<TEntity, bool>> condition, int pagesize, int pageindex,
|
||||
bool istotal)
|
||||
{
|
||||
return Dbcontext.GetList<TEntity, TId>(condition, pagesize, pageindex, istotal);
|
||||
}
|
||||
|
||||
public Task<PageData<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> condition, int pagesize,
|
||||
int pageindex, bool istotal)
|
||||
{
|
||||
return Dbcontext.GetListAsync<TEntity, TId>(condition, pagesize, pageindex, istotal);
|
||||
}
|
||||
|
||||
public List<TEntity> GetList(Expression<Func<TEntity, bool>> condition)
|
||||
{
|
||||
return Dbcontext.GetList<TEntity, TId>(condition);
|
||||
}
|
||||
|
||||
public Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> condition)
|
||||
{
|
||||
return Dbcontext.GetListAsync<TEntity, TId>(condition);
|
||||
}
|
||||
|
||||
public List<TEntity> TopN(Expression<Func<TEntity, bool>> condition, int topN)
|
||||
{
|
||||
return Dbcontext.TopN<TEntity, TId>(condition, topN);
|
||||
}
|
||||
|
||||
public Task<List<TEntity>> TopNAsync(Expression<Func<TEntity, bool>> condition, int topN)
|
||||
{
|
||||
return Dbcontext.TopNAsync<TEntity, TId>(condition, topN);
|
||||
}
|
||||
|
||||
public IQueryable<TEntity> GetListQueryable(Expression<Func<TEntity, bool>> exp)
|
||||
{
|
||||
return Dbcontext.GetListQueryable<TEntity, TId>(exp);
|
||||
}
|
||||
|
||||
public bool Exists(Expression<Func<TEntity, bool>> exp)
|
||||
{
|
||||
return Dbcontext.Exists<TEntity, TId>(exp);
|
||||
}
|
||||
|
||||
public Task<bool> ExistsAsync(Expression<Func<TEntity, bool>> condition)
|
||||
{
|
||||
return Dbcontext.ExistsAsync<TEntity, TId>(condition);
|
||||
}
|
||||
|
||||
public IQueryable<TEntity> GetQueryable()
|
||||
{
|
||||
return Dbcontext.Set<TEntity>().AsNoTracking();
|
||||
}
|
||||
public DbContext DbContext()
|
||||
{
|
||||
return Dbcontext;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.DDD;
|
||||
using Hncore.Infrastructure.EntitiesExtension;
|
||||
|
||||
namespace Hncore.Infrastructure.EF
|
||||
{
|
||||
public static class QueryExtension
|
||||
{
|
||||
public static TEntity GetOne<TEntity, TId>(this DbContext dbcontext, Expression<Func<TEntity, bool>> exp)
|
||||
where TEntity : class, IEntity<TId>
|
||||
{
|
||||
return dbcontext.Set<TEntity>().AsNoTracking()
|
||||
.FirstOrDefault(exp);
|
||||
}
|
||||
|
||||
public static Task<TEntity> GetOneAsync<TEntity, TId>(this DbContext dbcontext,
|
||||
Expression<Func<TEntity, bool>> exp) where TEntity : class, IEntity<TId>
|
||||
{
|
||||
return dbcontext.Set<TEntity>().AsNoTracking()
|
||||
.FirstOrDefaultAsync(exp);
|
||||
}
|
||||
|
||||
public static PageData<TEntity> GetList<TEntity, TId>(this DbContext dbcontext,
|
||||
Expression<Func<TEntity, bool>> exp, int pagesize, int pageindex, bool istotal)
|
||||
where TEntity : class, IEntity<TId>
|
||||
{
|
||||
return dbcontext.Set<TEntity>().AsNoTracking()
|
||||
.Where(exp)
|
||||
.OrderByDescending(t => t.Id)
|
||||
.ListPager(pagesize, pageindex, istotal);
|
||||
}
|
||||
|
||||
public static Task<PageData<TEntity>> GetListAsync<TEntity, TId>(this DbContext dbcontext,
|
||||
Expression<Func<TEntity, bool>> exp, int pagesize, int pageindex, bool istotal)
|
||||
where TEntity : class, IEntity<TId>
|
||||
{
|
||||
return dbcontext.Set<TEntity>().AsNoTracking()
|
||||
.Where(exp)
|
||||
.OrderByDescending(t => t.Id)
|
||||
.ListPagerAsync(pagesize, pageindex, istotal);
|
||||
}
|
||||
|
||||
public static List<TEntity> GetList<TEntity, TId>(this DbContext dbcontext, Expression<Func<TEntity, bool>> exp)
|
||||
where TEntity : class, IEntity<TId>
|
||||
{
|
||||
return dbcontext.Set<TEntity>().AsNoTracking()
|
||||
.Where(exp)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static Task<List<TEntity>> GetListAsync<TEntity, TId>(this DbContext dbcontext,
|
||||
Expression<Func<TEntity, bool>> exp)
|
||||
where TEntity : class, IEntity<TId>
|
||||
{
|
||||
return dbcontext.Set<TEntity>().AsNoTracking()
|
||||
.Where(exp)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public static IQueryable<TEntity> GetListQueryable<TEntity, TId>(this DbContext dbcontext,
|
||||
Expression<Func<TEntity, bool>> exp)
|
||||
where TEntity : class, IEntity<TId>
|
||||
{
|
||||
return dbcontext.Set<TEntity>().AsNoTracking()
|
||||
.Where(exp);
|
||||
}
|
||||
|
||||
public static bool Exists<TEntity, TId>(this DbContext dbcontext, Expression<Func<TEntity, bool>> exp)
|
||||
where TEntity : class, IEntity<TId>
|
||||
{
|
||||
return dbcontext.Set<TEntity>().AsNoTracking()
|
||||
.Any(exp);
|
||||
}
|
||||
|
||||
public static Task<bool> ExistsAsync<TEntity, TId>(this DbContext dbcontext,
|
||||
Expression<Func<TEntity, bool>> exp)
|
||||
where TEntity : class, IEntity<TId>
|
||||
{
|
||||
return dbcontext.Set<TEntity>().AsNoTracking()
|
||||
.AnyAsync(exp);
|
||||
}
|
||||
|
||||
public static List<TEntity> TopN<TEntity, TId>(this DbContext dbcontext,
|
||||
Expression<Func<TEntity, bool>> condition, int topN)
|
||||
where TEntity : class, IEntity<TId>
|
||||
{
|
||||
return dbcontext.Set<TEntity>().AsNoTracking()
|
||||
.Where(condition)
|
||||
.TopN(topN)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static Task<List<TEntity>> TopNAsync<TEntity, TId>(this DbContext dbcontext,
|
||||
Expression<Func<TEntity, bool>> condition, int topN)
|
||||
where TEntity : class, IEntity<TId>
|
||||
{
|
||||
return dbcontext.Set<TEntity>().AsNoTracking()
|
||||
.Where(condition)
|
||||
.TopN(topN)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Hncore.Infrastructure.DDD;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
|
||||
namespace Hncore.Infrastructure.EF
|
||||
{
|
||||
public class RepositoryBase<TEntity, TId> : IRepository<TEntity, TId>
|
||||
where TEntity : Entity<TId>
|
||||
{
|
||||
protected DbContext Dbcontext;
|
||||
|
||||
public RepositoryBase(IRepositoryDbContext dbContext)
|
||||
{
|
||||
Dbcontext = dbContext.DbContext;
|
||||
}
|
||||
|
||||
public TEntity FindById(TId id)
|
||||
{
|
||||
return Dbcontext.Set<TEntity>().Find(id);
|
||||
}
|
||||
|
||||
public Task<TEntity> FindByIdAsync(TId id)
|
||||
{
|
||||
return Dbcontext.Set<TEntity>().FindAsync(id);
|
||||
}
|
||||
|
||||
public void Add(TEntity entity)
|
||||
{
|
||||
Dbcontext.Set<TEntity>().Add(entity);
|
||||
}
|
||||
|
||||
|
||||
public Task AddAsync(TEntity entity)
|
||||
{
|
||||
return Dbcontext.Set<TEntity>().AddAsync(entity);
|
||||
}
|
||||
/// <summary>
|
||||
/// 批量添加
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
public void AddRange(List<TEntity> entity)
|
||||
{
|
||||
Dbcontext.Set<TEntity>().AddRange(entity);
|
||||
}
|
||||
/// <summary>
|
||||
/// 批量添加
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
public Task AddRangeAsync(List<TEntity> entity)
|
||||
{
|
||||
return Dbcontext.Set<TEntity>().AddRangeAsync(entity);
|
||||
}
|
||||
/// <summary>
|
||||
/// 批量修改
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
public void UpdateRange(List<TEntity> entity)
|
||||
{
|
||||
Dbcontext.Set<TEntity>().UpdateRange(entity);
|
||||
}
|
||||
/// <summary>
|
||||
/// 批量删除
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
public void RemoveRange(List<TEntity> entity)
|
||||
{
|
||||
Dbcontext.Set<TEntity>().RemoveRange(entity);
|
||||
}
|
||||
|
||||
public void Remove(TEntity entity)
|
||||
{
|
||||
Dbcontext.Set<TEntity>().Remove(entity);
|
||||
}
|
||||
public void Update(TEntity entity)
|
||||
{
|
||||
Dbcontext.Set<TEntity>().Update(entity);
|
||||
}
|
||||
|
||||
public IQueryable<TEntity> GetQueryable()
|
||||
{
|
||||
return Dbcontext.Set<TEntity>();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
vs
|
||||
Add-Migration
|
||||
Update-Database
|
||||
|
||||
|
||||
|
||||
cli
|
||||
dotnet ef migrations add init
|
||||
|
||||
dotnet ef database update
|
||||
|
||||
输出脚本
|
||||
dotnet ef migrations script
|
||||
@@ -1,48 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Hncore.Infrastructure.EntitiesExtension
|
||||
{
|
||||
public class CommonEqualityComparer<T, V> : IEqualityComparer<T>
|
||||
{
|
||||
private Func<T, V> keySelector;
|
||||
private IEqualityComparer<V> comparer;
|
||||
|
||||
public CommonEqualityComparer(Func<T, V> keySelector, IEqualityComparer<V> comparer)
|
||||
{
|
||||
this.keySelector = keySelector;
|
||||
this.comparer = comparer;
|
||||
}
|
||||
|
||||
public CommonEqualityComparer(Func<T, V> keySelector)
|
||||
: this(keySelector, EqualityComparer<V>.Default)
|
||||
{ }
|
||||
|
||||
public bool Equals(T x, T y)
|
||||
{
|
||||
return comparer.Equals(keySelector(x), keySelector(y));
|
||||
}
|
||||
|
||||
public int GetHashCode(T obj)
|
||||
{
|
||||
return comparer.GetHashCode(keySelector(obj));
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 扩展类
|
||||
/// </summary>
|
||||
public static class DistinctExtensions
|
||||
{
|
||||
public static IEnumerable<T> Distinctx<T, V>(this IEnumerable<T> source, Func<T, V> keySelector)
|
||||
{
|
||||
return source.Distinct(new CommonEqualityComparer<T, V>(keySelector));
|
||||
}
|
||||
|
||||
public static IEnumerable<T> Distinctx<T, V>(this IEnumerable<T> source, Func<T, V> keySelector, IEqualityComparer<V> comparer)
|
||||
{
|
||||
return source.Distinct(new CommonEqualityComparer<T, V>(keySelector, comparer));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Hncore.Infrastructure.EntitiesExtension
|
||||
{
|
||||
internal class ConditionBuilder : ExpressionVisitor
|
||||
{
|
||||
private List<object> m_arguments;
|
||||
private Stack<string> m_conditionParts;
|
||||
|
||||
public string Condition { get; private set; }
|
||||
|
||||
public object[] Arguments { get; private set; }
|
||||
|
||||
public void Build(Expression expression)
|
||||
{
|
||||
PartialEvaluator evaluator = new PartialEvaluator();
|
||||
Expression evaluatedExpression = evaluator.Eval(expression);
|
||||
|
||||
this.m_arguments = new List<object>();
|
||||
this.m_conditionParts = new Stack<string>();
|
||||
|
||||
this.Visit(evaluatedExpression);
|
||||
|
||||
this.Arguments = this.m_arguments.ToArray();
|
||||
this.Condition = this.m_conditionParts.Count > 0 ? this.m_conditionParts.Pop() : null;
|
||||
}
|
||||
|
||||
protected override Expression VisitBinary(BinaryExpression b)
|
||||
{
|
||||
if (b == null) return b;
|
||||
|
||||
string opr;
|
||||
switch (b.NodeType)
|
||||
{
|
||||
case ExpressionType.Equal:
|
||||
opr = "=";
|
||||
break;
|
||||
case ExpressionType.NotEqual:
|
||||
opr = "<>";
|
||||
break;
|
||||
case ExpressionType.GreaterThan:
|
||||
opr = ">";
|
||||
break;
|
||||
case ExpressionType.GreaterThanOrEqual:
|
||||
opr = ">=";
|
||||
break;
|
||||
case ExpressionType.LessThan:
|
||||
opr = "<";
|
||||
break;
|
||||
case ExpressionType.LessThanOrEqual:
|
||||
opr = "<=";
|
||||
break;
|
||||
case ExpressionType.AndAlso:
|
||||
opr = "AND";
|
||||
break;
|
||||
case ExpressionType.OrElse:
|
||||
opr = "OR";
|
||||
break;
|
||||
case ExpressionType.Add:
|
||||
opr = "+";
|
||||
break;
|
||||
case ExpressionType.Subtract:
|
||||
opr = "-";
|
||||
break;
|
||||
case ExpressionType.Multiply:
|
||||
opr = "*";
|
||||
break;
|
||||
case ExpressionType.Divide:
|
||||
opr = "/";
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException(b.NodeType + "is not supported.");
|
||||
}
|
||||
|
||||
this.Visit(b.Left);
|
||||
this.Visit(b.Right);
|
||||
|
||||
string right = this.m_conditionParts.Pop();
|
||||
string left = this.m_conditionParts.Pop();
|
||||
|
||||
string condition = String.Format("({0} {1} {2})", left, opr, right);
|
||||
this.m_conditionParts.Push(condition);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
protected override Expression VisitConstant(ConstantExpression c)
|
||||
{
|
||||
if (c == null) return c;
|
||||
|
||||
this.m_arguments.Add(c.Value);
|
||||
this.m_conditionParts.Push(String.Format("{{{0}}}", this.m_arguments.Count - 1));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
protected override Expression VisitMemberAccess(MemberExpression m)
|
||||
{
|
||||
if (m == null) return m;
|
||||
|
||||
PropertyInfo propertyInfo = m.Member as PropertyInfo;
|
||||
if (propertyInfo == null) return m;
|
||||
|
||||
this.m_conditionParts.Push(String.Format("[{0}]", propertyInfo.Name));
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
protected override Expression VisitMethodCall(MethodCallExpression m)
|
||||
{
|
||||
if (m == null) return m;
|
||||
|
||||
string format;
|
||||
switch (m.Method.Name)
|
||||
{
|
||||
case "StartsWith":
|
||||
format = "({0} LIKE {1}+'%')";
|
||||
break;
|
||||
|
||||
case "Contains":
|
||||
format = "({0} LIKE '%'+{1}+'%')";
|
||||
break;
|
||||
|
||||
case "EndsWith":
|
||||
format = "({0} LIKE '%'+{1})";
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException(m.NodeType + " is not supported!");
|
||||
}
|
||||
|
||||
this.Visit(m.Object);
|
||||
this.Visit(m.Arguments[0]);
|
||||
string right = this.m_conditionParts.Pop();
|
||||
string left = this.m_conditionParts.Pop();
|
||||
this.m_conditionParts.Push(String.Format(format, left, right));
|
||||
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Hncore.Infrastructure.EntitiesExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for add And and Or with parameters rebinder
|
||||
/// </summary>
|
||||
public static class ExpressionBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Compose two expression and merge all in a new expression
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of params in expression</typeparam>
|
||||
/// <param name="first">Expression instance</param>
|
||||
/// <param name="second">Expression to merge</param>
|
||||
/// <param name="merge">Function to merge</param>
|
||||
/// <returns>New merged expressions</returns>
|
||||
public static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
|
||||
{
|
||||
// build parameter map (from parameters of second to parameters of first)
|
||||
var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
|
||||
|
||||
// replace parameters in the second lambda expression with parameters from the first
|
||||
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
|
||||
// apply composition of lambda expression bodies to parameters from the first expression
|
||||
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
|
||||
}
|
||||
/// <summary>
|
||||
/// And operator
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of params in expression</typeparam>
|
||||
/// <param name="first">Right Expression in AND operation</param>
|
||||
/// <param name="second">Left Expression in And operation</param>
|
||||
/// <returns>New AND expression</returns>
|
||||
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
|
||||
{
|
||||
return first.Compose(second, Expression.AndAlso);
|
||||
}
|
||||
/// <summary>
|
||||
/// Or operator
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of param in expression</typeparam>
|
||||
/// <param name="first">Right expression in OR operation</param>
|
||||
/// <param name="second">Left expression in OR operation</param>
|
||||
/// <returns>New Or expressions</returns>
|
||||
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
|
||||
{
|
||||
return first.Compose(second, Expression.Or);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,364 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Hncore.Infrastructure.EntitiesExtension
|
||||
{
|
||||
public abstract class ExpressionVisitor
|
||||
{
|
||||
protected ExpressionVisitor() { }
|
||||
|
||||
protected virtual Expression Visit(Expression exp)
|
||||
{
|
||||
if (exp == null)
|
||||
return exp;
|
||||
switch (exp.NodeType)
|
||||
{
|
||||
case ExpressionType.Negate:
|
||||
case ExpressionType.NegateChecked:
|
||||
case ExpressionType.Not:
|
||||
case ExpressionType.Convert:
|
||||
case ExpressionType.ConvertChecked:
|
||||
case ExpressionType.ArrayLength:
|
||||
case ExpressionType.Quote:
|
||||
case ExpressionType.TypeAs:
|
||||
return this.VisitUnary((UnaryExpression)exp);
|
||||
case ExpressionType.Add:
|
||||
case ExpressionType.AddChecked:
|
||||
case ExpressionType.Subtract:
|
||||
case ExpressionType.SubtractChecked:
|
||||
case ExpressionType.Multiply:
|
||||
case ExpressionType.MultiplyChecked:
|
||||
case ExpressionType.Divide:
|
||||
case ExpressionType.Modulo:
|
||||
case ExpressionType.And:
|
||||
case ExpressionType.AndAlso:
|
||||
case ExpressionType.Or:
|
||||
case ExpressionType.OrElse:
|
||||
case ExpressionType.LessThan:
|
||||
case ExpressionType.LessThanOrEqual:
|
||||
case ExpressionType.GreaterThan:
|
||||
case ExpressionType.GreaterThanOrEqual:
|
||||
case ExpressionType.Equal:
|
||||
case ExpressionType.NotEqual:
|
||||
case ExpressionType.Coalesce:
|
||||
case ExpressionType.ArrayIndex:
|
||||
case ExpressionType.RightShift:
|
||||
case ExpressionType.LeftShift:
|
||||
case ExpressionType.ExclusiveOr:
|
||||
return this.VisitBinary((BinaryExpression)exp);
|
||||
case ExpressionType.TypeIs:
|
||||
return this.VisitTypeIs((TypeBinaryExpression)exp);
|
||||
case ExpressionType.Conditional:
|
||||
return this.VisitConditional((ConditionalExpression)exp);
|
||||
case ExpressionType.Constant:
|
||||
return this.VisitConstant((ConstantExpression)exp);
|
||||
case ExpressionType.Parameter:
|
||||
return this.VisitParameter((ParameterExpression)exp);
|
||||
case ExpressionType.MemberAccess:
|
||||
return this.VisitMemberAccess((MemberExpression)exp);
|
||||
case ExpressionType.Call:
|
||||
return this.VisitMethodCall((MethodCallExpression)exp);
|
||||
case ExpressionType.Lambda:
|
||||
return this.VisitLambda((LambdaExpression)exp);
|
||||
case ExpressionType.New:
|
||||
return this.VisitNew((NewExpression)exp);
|
||||
case ExpressionType.NewArrayInit:
|
||||
case ExpressionType.NewArrayBounds:
|
||||
return this.VisitNewArray((NewArrayExpression)exp);
|
||||
case ExpressionType.Invoke:
|
||||
return this.VisitInvocation((InvocationExpression)exp);
|
||||
case ExpressionType.MemberInit:
|
||||
return this.VisitMemberInit((MemberInitExpression)exp);
|
||||
case ExpressionType.ListInit:
|
||||
return this.VisitListInit((ListInitExpression)exp);
|
||||
default:
|
||||
throw new Exception(string.Format("Unhandled expression type: '{0}'", exp.NodeType));
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual MemberBinding VisitBinding(MemberBinding binding)
|
||||
{
|
||||
switch (binding.BindingType)
|
||||
{
|
||||
case MemberBindingType.Assignment:
|
||||
return this.VisitMemberAssignment((MemberAssignment)binding);
|
||||
case MemberBindingType.MemberBinding:
|
||||
return this.VisitMemberMemberBinding((MemberMemberBinding)binding);
|
||||
case MemberBindingType.ListBinding:
|
||||
return this.VisitMemberListBinding((MemberListBinding)binding);
|
||||
default:
|
||||
throw new Exception(string.Format("Unhandled binding type '{0}'", binding.BindingType));
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual ElementInit VisitElementInitializer(ElementInit initializer)
|
||||
{
|
||||
ReadOnlyCollection<Expression> arguments = this.VisitExpressionList(initializer.Arguments);
|
||||
if (arguments != initializer.Arguments)
|
||||
{
|
||||
return Expression.ElementInit(initializer.AddMethod, arguments);
|
||||
}
|
||||
return initializer;
|
||||
}
|
||||
|
||||
protected virtual Expression VisitUnary(UnaryExpression u)
|
||||
{
|
||||
Expression operand = this.Visit(u.Operand);
|
||||
if (operand != u.Operand)
|
||||
{
|
||||
return Expression.MakeUnary(u.NodeType, operand, u.Type, u.Method);
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
protected virtual Expression VisitBinary(BinaryExpression b)
|
||||
{
|
||||
Expression left = this.Visit(b.Left);
|
||||
Expression right = this.Visit(b.Right);
|
||||
Expression conversion = this.Visit(b.Conversion);
|
||||
if (left != b.Left || right != b.Right || conversion != b.Conversion)
|
||||
{
|
||||
if (b.NodeType == ExpressionType.Coalesce && b.Conversion != null)
|
||||
return Expression.Coalesce(left, right, conversion as LambdaExpression);
|
||||
else
|
||||
return Expression.MakeBinary(b.NodeType, left, right, b.IsLiftedToNull, b.Method);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
protected virtual Expression VisitTypeIs(TypeBinaryExpression b)
|
||||
{
|
||||
Expression expr = this.Visit(b.Expression);
|
||||
if (expr != b.Expression)
|
||||
{
|
||||
return Expression.TypeIs(expr, b.TypeOperand);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
protected virtual Expression VisitConstant(ConstantExpression c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
|
||||
protected virtual Expression VisitConditional(ConditionalExpression c)
|
||||
{
|
||||
Expression test = this.Visit(c.Test);
|
||||
Expression ifTrue = this.Visit(c.IfTrue);
|
||||
Expression ifFalse = this.Visit(c.IfFalse);
|
||||
if (test != c.Test || ifTrue != c.IfTrue || ifFalse != c.IfFalse)
|
||||
{
|
||||
return Expression.Condition(test, ifTrue, ifFalse);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
protected virtual Expression VisitParameter(ParameterExpression p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
protected virtual Expression VisitMemberAccess(MemberExpression m)
|
||||
{
|
||||
Expression exp = this.Visit(m.Expression);
|
||||
if (exp != m.Expression)
|
||||
{
|
||||
return Expression.MakeMemberAccess(exp, m.Member);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
protected virtual Expression VisitMethodCall(MethodCallExpression m)
|
||||
{
|
||||
Expression obj = this.Visit(m.Object);
|
||||
IEnumerable<Expression> args = this.VisitExpressionList(m.Arguments);
|
||||
if (obj != m.Object || args != m.Arguments)
|
||||
{
|
||||
return Expression.Call(obj, m.Method, args);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
protected virtual ReadOnlyCollection<Expression> VisitExpressionList(ReadOnlyCollection<Expression> original)
|
||||
{
|
||||
List<Expression> list = null;
|
||||
for (int i = 0, n = original.Count; i < n; i++)
|
||||
{
|
||||
Expression p = this.Visit(original[i]);
|
||||
if (list != null)
|
||||
{
|
||||
list.Add(p);
|
||||
}
|
||||
else if (p != original[i])
|
||||
{
|
||||
list = new List<Expression>(n);
|
||||
for (int j = 0; j < i; j++)
|
||||
{
|
||||
list.Add(original[j]);
|
||||
}
|
||||
list.Add(p);
|
||||
}
|
||||
}
|
||||
if (list != null)
|
||||
{
|
||||
return list.AsReadOnly();
|
||||
}
|
||||
return original;
|
||||
}
|
||||
|
||||
protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment assignment)
|
||||
{
|
||||
Expression e = this.Visit(assignment.Expression);
|
||||
if (e != assignment.Expression)
|
||||
{
|
||||
return Expression.Bind(assignment.Member, e);
|
||||
}
|
||||
return assignment;
|
||||
}
|
||||
|
||||
protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding)
|
||||
{
|
||||
IEnumerable<MemberBinding> bindings = this.VisitBindingList(binding.Bindings);
|
||||
if (bindings != binding.Bindings)
|
||||
{
|
||||
return Expression.MemberBind(binding.Member, bindings);
|
||||
}
|
||||
return binding;
|
||||
}
|
||||
|
||||
protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding)
|
||||
{
|
||||
IEnumerable<ElementInit> initializers = this.VisitElementInitializerList(binding.Initializers);
|
||||
if (initializers != binding.Initializers)
|
||||
{
|
||||
return Expression.ListBind(binding.Member, initializers);
|
||||
}
|
||||
return binding;
|
||||
}
|
||||
|
||||
protected virtual IEnumerable<MemberBinding> VisitBindingList(ReadOnlyCollection<MemberBinding> original)
|
||||
{
|
||||
List<MemberBinding> list = null;
|
||||
for (int i = 0, n = original.Count; i < n; i++)
|
||||
{
|
||||
MemberBinding b = this.VisitBinding(original[i]);
|
||||
if (list != null)
|
||||
{
|
||||
list.Add(b);
|
||||
}
|
||||
else if (b != original[i])
|
||||
{
|
||||
list = new List<MemberBinding>(n);
|
||||
for (int j = 0; j < i; j++)
|
||||
{
|
||||
list.Add(original[j]);
|
||||
}
|
||||
list.Add(b);
|
||||
}
|
||||
}
|
||||
if (list != null)
|
||||
return list;
|
||||
return original;
|
||||
}
|
||||
|
||||
protected virtual IEnumerable<ElementInit> VisitElementInitializerList(ReadOnlyCollection<ElementInit> original)
|
||||
{
|
||||
List<ElementInit> list = null;
|
||||
for (int i = 0, n = original.Count; i < n; i++)
|
||||
{
|
||||
ElementInit init = this.VisitElementInitializer(original[i]);
|
||||
if (list != null)
|
||||
{
|
||||
list.Add(init);
|
||||
}
|
||||
else if (init != original[i])
|
||||
{
|
||||
list = new List<ElementInit>(n);
|
||||
for (int j = 0; j < i; j++)
|
||||
{
|
||||
list.Add(original[j]);
|
||||
}
|
||||
list.Add(init);
|
||||
}
|
||||
}
|
||||
if (list != null)
|
||||
return list;
|
||||
return original;
|
||||
}
|
||||
|
||||
protected virtual Expression VisitLambda(LambdaExpression lambda)
|
||||
{
|
||||
Expression body = this.Visit(lambda.Body);
|
||||
if (body != lambda.Body)
|
||||
{
|
||||
return Expression.Lambda(lambda.Type, body, lambda.Parameters);
|
||||
}
|
||||
return lambda;
|
||||
}
|
||||
|
||||
protected virtual NewExpression VisitNew(NewExpression nex)
|
||||
{
|
||||
IEnumerable<Expression> args = this.VisitExpressionList(nex.Arguments);
|
||||
if (args != nex.Arguments)
|
||||
{
|
||||
if (nex.Members != null)
|
||||
return Expression.New(nex.Constructor, args, nex.Members);
|
||||
else
|
||||
return Expression.New(nex.Constructor, args);
|
||||
}
|
||||
return nex;
|
||||
}
|
||||
|
||||
protected virtual Expression VisitMemberInit(MemberInitExpression init)
|
||||
{
|
||||
NewExpression n = this.VisitNew(init.NewExpression);
|
||||
IEnumerable<MemberBinding> bindings = this.VisitBindingList(init.Bindings);
|
||||
if (n != init.NewExpression || bindings != init.Bindings)
|
||||
{
|
||||
return Expression.MemberInit(n, bindings);
|
||||
}
|
||||
return init;
|
||||
}
|
||||
|
||||
protected virtual Expression VisitListInit(ListInitExpression init)
|
||||
{
|
||||
NewExpression n = this.VisitNew(init.NewExpression);
|
||||
IEnumerable<ElementInit> initializers = this.VisitElementInitializerList(init.Initializers);
|
||||
if (n != init.NewExpression || initializers != init.Initializers)
|
||||
{
|
||||
return Expression.ListInit(n, initializers);
|
||||
}
|
||||
return init;
|
||||
}
|
||||
|
||||
protected virtual Expression VisitNewArray(NewArrayExpression na)
|
||||
{
|
||||
IEnumerable<Expression> exprs = this.VisitExpressionList(na.Expressions);
|
||||
if (exprs != na.Expressions)
|
||||
{
|
||||
if (na.NodeType == ExpressionType.NewArrayInit)
|
||||
{
|
||||
return Expression.NewArrayInit(na.Type.GetElementType(), exprs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Expression.NewArrayBounds(na.Type.GetElementType(), exprs);
|
||||
}
|
||||
}
|
||||
return na;
|
||||
}
|
||||
|
||||
protected virtual Expression VisitInvocation(InvocationExpression iv)
|
||||
{
|
||||
IEnumerable<Expression> args = this.VisitExpressionList(iv.Arguments);
|
||||
Expression expr = this.Visit(iv.Expression);
|
||||
if (args != iv.Arguments || expr != iv.Expression)
|
||||
{
|
||||
return Expression.Invoke(expr, args);
|
||||
}
|
||||
return iv;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Hncore.Infrastructure.EntitiesExtension
|
||||
{
|
||||
public static class IQueryableExtend
|
||||
{
|
||||
#region 返回IQueryable<T>前几条数据
|
||||
|
||||
/// <summary>
|
||||
/// 返回IQueryable前几条数据
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="TopN"></param>
|
||||
/// <returns></returns>
|
||||
public static IQueryable<T> TopN<T>(this IQueryable<T> query, int TopN)
|
||||
{
|
||||
return query.Take(TopN);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 对IQueryable<T>进行分页
|
||||
|
||||
/// <summary>
|
||||
/// 对IQueryable进行分页
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="PageSize">每页多少条数据</param>
|
||||
/// <param name="PageIndex">当前页</param>
|
||||
/// <returns></returns>
|
||||
public static IQueryable<T> QueryPager<T>(this IQueryable<T> query, int PageSize, int PageIndex)
|
||||
{
|
||||
if (PageIndex <= 0)
|
||||
{
|
||||
PageIndex = 1;
|
||||
}
|
||||
|
||||
if (PageSize <= 0)
|
||||
{
|
||||
PageSize = 1;
|
||||
}
|
||||
|
||||
if (PageSize > 0)
|
||||
return query.Skip((PageIndex - 1) * PageSize).Take(PageSize);
|
||||
return query;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 得到IQueryable<T>的分页后实体集合
|
||||
|
||||
/// <summary>
|
||||
/// 得到IQueryable的分页后实体集合
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="pageSize">每页多少条数据</param>
|
||||
/// <param name="pageIndex">当前页</param>
|
||||
/// <param name="isTotal">是否统计总行数</param>
|
||||
/// <returns></returns>
|
||||
public static PageData<T> ListPager<T>(this IQueryable<T> query, int pageSize, int pageIndex, bool isTotal)
|
||||
{
|
||||
PageData<T> list = new PageData<T>();
|
||||
|
||||
if (isTotal)
|
||||
{
|
||||
list.RowCount = query.Count();
|
||||
}
|
||||
|
||||
list.List = query.QueryPager<T>(pageSize, pageIndex).ToList();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 得到IQueryable的分页后实体集合
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="pageSize">每页多少条数据</param>
|
||||
/// <param name="pageIndex">当前页</param>
|
||||
/// <param name="isTotal">是否统计总行数</param>
|
||||
/// <returns></returns>
|
||||
public static async Task<PageData<T>> ListPagerAsync<T>(this IQueryable<T> query, int pageSize, int pageIndex,
|
||||
bool isTotal)
|
||||
{
|
||||
PageData<T> list = new PageData<T>();
|
||||
|
||||
if (isTotal)
|
||||
{
|
||||
list.RowCount = await query.CountAsync();
|
||||
}
|
||||
|
||||
list.List = await query.QueryPager<T>(pageSize, pageIndex).ToListAsync();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Hncore.Infrastructure.EntitiesExtension
|
||||
{
|
||||
public class ParameterRebinder : ExpressionVisitor
|
||||
{
|
||||
private readonly Dictionary<ParameterExpression, ParameterExpression> map;
|
||||
|
||||
/// <summary>
|
||||
/// Default construcotr
|
||||
/// </summary>
|
||||
/// <param name="map">Map specification</param>
|
||||
public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
|
||||
{
|
||||
this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
|
||||
}
|
||||
/// <summary>
|
||||
/// Replate parameters in expression with a Map information
|
||||
/// </summary>
|
||||
/// <param name="map">Map information</param>
|
||||
/// <param name="exp">Expression to replace parameters</param>
|
||||
/// <returns>Expression with parameters replaced</returns>
|
||||
public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
|
||||
{
|
||||
return new ParameterRebinder(map).Visit(exp);
|
||||
}
|
||||
/// <summary>
|
||||
/// Visit pattern method
|
||||
/// </summary>
|
||||
/// <param name="p">A Parameter expression</param>
|
||||
/// <returns>New visited expression</returns>
|
||||
protected override Expression VisitParameter(ParameterExpression p)
|
||||
{
|
||||
ParameterExpression replacement;
|
||||
if (map.TryGetValue(p, out replacement))
|
||||
{
|
||||
p = replacement;
|
||||
}
|
||||
|
||||
return base.VisitParameter(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Hncore.Infrastructure.EntitiesExtension
|
||||
{
|
||||
public class PartialEvaluator : ExpressionVisitor
|
||||
{
|
||||
private Func<Expression, bool> m_fnCanBeEvaluated;
|
||||
private HashSet<Expression> m_candidates;
|
||||
|
||||
public PartialEvaluator()
|
||||
: this(CanBeEvaluatedLocally)
|
||||
{ }
|
||||
|
||||
public PartialEvaluator(Func<Expression, bool> fnCanBeEvaluated)
|
||||
{
|
||||
this.m_fnCanBeEvaluated = fnCanBeEvaluated;
|
||||
}
|
||||
|
||||
public Expression Eval(Expression exp)
|
||||
{
|
||||
this.m_candidates = new Nominator(this.m_fnCanBeEvaluated).Nominate(exp);
|
||||
|
||||
return this.Visit(exp);
|
||||
}
|
||||
|
||||
protected override Expression Visit(Expression exp)
|
||||
{
|
||||
if (exp == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.m_candidates.Contains(exp))
|
||||
{
|
||||
return this.Evaluate(exp);
|
||||
}
|
||||
|
||||
return base.Visit(exp);
|
||||
}
|
||||
|
||||
private Expression Evaluate(Expression e)
|
||||
{
|
||||
if (e.NodeType == ExpressionType.Constant)
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
LambdaExpression lambda = Expression.Lambda(e);
|
||||
Delegate fn = lambda.Compile();
|
||||
|
||||
return Expression.Constant(fn.DynamicInvoke(null), e.Type);
|
||||
}
|
||||
|
||||
private static bool CanBeEvaluatedLocally(Expression exp)
|
||||
{
|
||||
return exp.NodeType != ExpressionType.Parameter;
|
||||
}
|
||||
|
||||
#region Nominator
|
||||
|
||||
/// <summary>
|
||||
/// Performs bottom-up analysis to determine which nodes can possibly
|
||||
/// be part of an evaluated sub-tree.
|
||||
/// </summary>
|
||||
private class Nominator : ExpressionVisitor
|
||||
{
|
||||
private Func<Expression, bool> m_fnCanBeEvaluated;
|
||||
private HashSet<Expression> m_candidates;
|
||||
private bool m_cannotBeEvaluated;
|
||||
|
||||
internal Nominator(Func<Expression, bool> fnCanBeEvaluated)
|
||||
{
|
||||
this.m_fnCanBeEvaluated = fnCanBeEvaluated;
|
||||
}
|
||||
|
||||
internal HashSet<Expression> Nominate(Expression expression)
|
||||
{
|
||||
this.m_candidates = new HashSet<Expression>();
|
||||
this.Visit(expression);
|
||||
return this.m_candidates;
|
||||
}
|
||||
|
||||
protected override Expression Visit(Expression expression)
|
||||
{
|
||||
if (expression != null)
|
||||
{
|
||||
bool saveCannotBeEvaluated = this.m_cannotBeEvaluated;
|
||||
this.m_cannotBeEvaluated = false;
|
||||
|
||||
base.Visit(expression);
|
||||
|
||||
if (!this.m_cannotBeEvaluated)
|
||||
{
|
||||
if (this.m_fnCanBeEvaluated(expression))
|
||||
{
|
||||
this.m_candidates.Add(expression);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.m_cannotBeEvaluated = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.m_cannotBeEvaluated |= saveCannotBeEvaluated;
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Infrastructure.Events
|
||||
{
|
||||
internal class ActionEventHandler<TEventData> : IEventHandler<TEventData> where TEventData : IEventData
|
||||
{
|
||||
public Action<TEventData> Action { get; private set; }
|
||||
|
||||
public virtual bool Ansyc { get; set; }
|
||||
|
||||
public ActionEventHandler(Action<TEventData> handler)
|
||||
{
|
||||
Action = handler;
|
||||
}
|
||||
public void HandleEvent(TEventData eventData)
|
||||
{
|
||||
Action(eventData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Infrastructure.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// 事件总线
|
||||
/// </summary>
|
||||
public class EventBus
|
||||
{
|
||||
private static EventBus _eventBus = null;
|
||||
|
||||
public static EventBus Default
|
||||
{
|
||||
get { return _eventBus ?? (_eventBus = new EventBus()); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定义线程安全集合
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<Type, List<IEventHandler>> _eventAndHandlerMapping;
|
||||
|
||||
public EventBus()
|
||||
{
|
||||
_eventAndHandlerMapping = new ConcurrentDictionary<Type, List<IEventHandler>>();
|
||||
MapEventToHandler();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///通过反射,将事件源与事件处理绑定
|
||||
/// </summary>
|
||||
private void MapEventToHandler()
|
||||
{
|
||||
// Assembly assembly = Assembly.GetEntryAssembly();
|
||||
|
||||
var allAssembly = AppDomain.CurrentDomain.GetAssemblies().Where(item => item.FullName.Contains("Microkj."));
|
||||
if (!allAssembly.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var assembly in allAssembly)
|
||||
{
|
||||
foreach (var type in assembly.GetTypes())
|
||||
{
|
||||
if (!type.IsGenericType && typeof(IEventHandler).IsAssignableFrom(type)) //判断当前类型是否实现了IEventHandler接口
|
||||
{
|
||||
Type handlerInterface = type.GetInterface("IEventHandler`1"); //获取该类实现的泛型接口
|
||||
if (handlerInterface != null)
|
||||
{
|
||||
Type eventDataType = handlerInterface.GetGenericArguments()[0]; // 获取泛型接口指定的参数类型
|
||||
|
||||
if (_eventAndHandlerMapping.ContainsKey(eventDataType))
|
||||
{
|
||||
List<IEventHandler> handlerTypes = _eventAndHandlerMapping[eventDataType];
|
||||
handlerTypes.Add(Activator.CreateInstance(type) as IEventHandler);
|
||||
_eventAndHandlerMapping[eventDataType] = handlerTypes;
|
||||
}
|
||||
else
|
||||
{
|
||||
var handlerTypes = new List<IEventHandler>
|
||||
{
|
||||
Activator.CreateInstance(type) as IEventHandler
|
||||
};
|
||||
_eventAndHandlerMapping[eventDataType] = handlerTypes;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 手动绑定事件源与事件处理
|
||||
/// </summary>
|
||||
/// <typeparam name="TEventData"></typeparam>
|
||||
/// <param name="eventHandler"></param>
|
||||
public void Register<TEventData>(IEventHandler eventHandler)
|
||||
{
|
||||
if (_eventAndHandlerMapping.Keys.Contains(typeof (TEventData)))
|
||||
{
|
||||
List<IEventHandler> handlerTypes = _eventAndHandlerMapping[typeof (TEventData)];
|
||||
if (!handlerTypes.Contains(eventHandler))
|
||||
{
|
||||
handlerTypes.Add(eventHandler);
|
||||
_eventAndHandlerMapping[typeof (TEventData)] = handlerTypes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_eventAndHandlerMapping.GetOrAdd(typeof (TEventData), (type) => new List<IEventHandler>())
|
||||
.Add(eventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Register<TEventData>(Action<TEventData> action) where TEventData : IEventData
|
||||
{
|
||||
var actionHandler = new ActionEventHandler<TEventData>(action);
|
||||
Register<TEventData>(actionHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 手动解除事件源与事件处理的绑定
|
||||
/// </summary>
|
||||
/// <typeparam name="TEventData"></typeparam>
|
||||
/// <param name="eventHandler"></param>
|
||||
public void UnRegister<TEventData>(Type eventHandler)
|
||||
{
|
||||
List<IEventHandler> handlerTypes = _eventAndHandlerMapping[typeof (TEventData)];
|
||||
|
||||
_eventAndHandlerMapping.GetOrAdd(typeof (TEventData), (type) => new List<IEventHandler>())
|
||||
.RemoveAll(t => t.GetType() == eventHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据事件源触发绑定的事件处理
|
||||
/// </summary>
|
||||
/// <typeparam name="TEventData"></typeparam>
|
||||
/// <param name="eventData"></param>
|
||||
public static void Publish<TEventData>(TEventData eventData) where TEventData : IEventData
|
||||
{
|
||||
List<IEventHandler> handlers = Default._eventAndHandlerMapping[typeof (TEventData)];
|
||||
|
||||
if (handlers != null && handlers.Count > 0)
|
||||
{
|
||||
foreach (var handler in handlers)
|
||||
{
|
||||
var eventHandler = handler as IEventHandler<TEventData>;
|
||||
if (eventHandler.Ansyc)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
eventHandler.HandleEvent(eventData);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
eventHandler.HandleEvent(eventData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Infrastructure.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// 事件源:描述事件信息,用于参数传递
|
||||
/// </summary>
|
||||
public class EventData<TData> : IEventData where TData:class
|
||||
{
|
||||
/// <summary>
|
||||
/// 事件发生的时间
|
||||
/// </summary>
|
||||
public DateTime EventTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 触发事件的对象
|
||||
/// </summary>
|
||||
public TData EventSource { get; set; }
|
||||
|
||||
object IEventData.EventSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.EventSource as TData;
|
||||
}
|
||||
|
||||
set { this.EventSource =(TData) value; }
|
||||
}
|
||||
|
||||
public EventData()
|
||||
{
|
||||
EventTime = DateTime.Now;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Infrastructure.Events
|
||||
{
|
||||
public interface IEventBus
|
||||
{
|
||||
void Register<TEventData>(IEventHandler eventHandler);
|
||||
|
||||
void Register<TEventData>(Action<TEventData> action) where TEventData : IEventData;
|
||||
|
||||
void UnRegister<TEventData>(Type eventHandler);
|
||||
|
||||
// void Trigger<TEventData>(TEventData eventData) where TEventData : IEventData;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Infrastructure.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// 定义事件源接口,所有的事件源都要实现该接口
|
||||
/// </summary>
|
||||
public interface IEventData
|
||||
{
|
||||
/// <summary>
|
||||
/// 事件发生的时间
|
||||
/// </summary>
|
||||
DateTime EventTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 触发事件的对象
|
||||
/// </summary>
|
||||
Object EventSource { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Infrastructure.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// 定义事件处理器公共接口,所有的事件处理都要实现该接口
|
||||
/// </summary>
|
||||
public interface IEventHandler
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 泛型事件处理器接口
|
||||
/// </summary>
|
||||
/// <typeparam name="TEventData"></typeparam>
|
||||
public interface IEventHandler<TEventData> : IEventHandler where TEventData : IEventData
|
||||
{
|
||||
bool Ansyc { get; set; }
|
||||
/// <summary>
|
||||
/// 事件处理器实现该方法来处理事件
|
||||
/// </summary>
|
||||
/// <param name="eventData"></param>
|
||||
void HandleEvent(TEventData eventData);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
/// <summary>
|
||||
/// 程序集扩展类
|
||||
/// </summary>
|
||||
public static class AssemblyExtension
|
||||
{
|
||||
/// <summary>
|
||||
///得到程序集友好名字
|
||||
/// </summary>
|
||||
/// <param name="para"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetFriendName(this Assembly asm)
|
||||
{
|
||||
return asm.ManifestModule?.Name?.TrimEnd(".dll".ToCharArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
/// <summary>
|
||||
/// bool类型扩展
|
||||
/// </summary>
|
||||
public static class BoolExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 转为bool
|
||||
/// </summary>
|
||||
/// <param name="para"></param>
|
||||
/// <returns></returns>
|
||||
public static bool ToBool(this bool? para)
|
||||
{
|
||||
if (para == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Convert.ToBoolean(para);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 转为bool
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static bool ToBool(this object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool.TryParse(obj.ToString(), out var para);
|
||||
|
||||
return para;
|
||||
}
|
||||
|
||||
public static bool ToBool(this sbyte? obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
sbyte num = (sbyte) obj;
|
||||
|
||||
if (num == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
public static class DateTimeExtension
|
||||
{
|
||||
public static string Format(this DateTime time, string format = "yyyy-MM-dd")
|
||||
{
|
||||
return time.ToString(format);
|
||||
}
|
||||
|
||||
|
||||
private static DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
public static long CurrentTimeMillis()
|
||||
{
|
||||
return (long) ((DateTime.UtcNow - Jan1st1970).TotalMilliseconds);
|
||||
}
|
||||
|
||||
public static long CurrentTimeMillis(DateTime time)
|
||||
{
|
||||
return (long) ((time.ToUniversalTime() - Jan1st1970).TotalMilliseconds);
|
||||
}
|
||||
|
||||
public static string Format(this DateTime? dateTime, string format = "yyyy-MM-dd")
|
||||
{
|
||||
return Convert.ToDateTime(dateTime).ToString(format);
|
||||
}
|
||||
|
||||
public static DateTime ToDateTime(this DateTime? dateTime, DateTime defaultTime)
|
||||
{
|
||||
if (dateTime != null)
|
||||
{
|
||||
return Convert.ToDateTime(dateTime);
|
||||
}
|
||||
|
||||
return defaultTime;
|
||||
}
|
||||
|
||||
public static bool Between(this DateTime time, DateTime beginTime, DateTime endTime)
|
||||
{
|
||||
return time >= beginTime && time <= endTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取得某月的第一天
|
||||
/// </summary>
|
||||
/// <param name="datetime">要取得月份第一天的时间</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime FirstDayOfMonth(this DateTime datetime)
|
||||
{
|
||||
return datetime.AddDays(1 - datetime.Day);
|
||||
}
|
||||
|
||||
/**/
|
||||
/// <summary>
|
||||
/// 取得某月的最后一天
|
||||
/// </summary>
|
||||
/// <param name="datetime">要取得月份最后一天的时间</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime LastDayOfMonth(this DateTime datetime)
|
||||
{
|
||||
return datetime.AddDays(1 - datetime.Day).AddMonths(1).AddDays(-1);
|
||||
}
|
||||
|
||||
/**/
|
||||
/// <summary>
|
||||
/// 取得上个月第一天
|
||||
/// </summary>
|
||||
/// <param name="datetime">要取得上个月第一天的当前时间</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime FirstDayOfPreviousMonth(this DateTime datetime)
|
||||
{
|
||||
return datetime.AddDays(1 - datetime.Day).AddMonths(-1);
|
||||
}
|
||||
|
||||
/**/
|
||||
/// <summary>
|
||||
/// 取得上个月的最后一天
|
||||
/// </summary>
|
||||
/// <param name="datetime">要取得上个月最后一天的当前时间</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime LastDayOfPrdviousMonth(this DateTime datetime)
|
||||
{
|
||||
return datetime.AddDays(1 - datetime.Day).AddDays(-1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取时间的Unix时间戳
|
||||
/// </summary>
|
||||
/// <param name="tm">时间对象</param>
|
||||
/// <returns>Unix时间戳</returns>
|
||||
///
|
||||
public static long GetUnixTimeStamp(this DateTime tm)
|
||||
{
|
||||
long result = (tm.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从Uninx转换时间
|
||||
/// </summary>
|
||||
/// <param name="tm">时间对象</param>
|
||||
/// <param name="timeStamp">时间戳</param>
|
||||
/// <returns>新时间对象</returns>
|
||||
///
|
||||
public static DateTime LoadFromUnixTimeStamp(this DateTime tm,double timeStamp)
|
||||
{
|
||||
DateTime startTime=TimeZoneInfo.ConvertTime(new System.DateTime(1970, 1, 1),TimeZoneInfo.Local);
|
||||
DateTime result=startTime.AddSeconds(timeStamp);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static DateTime LoadFromUnixTimeStamp(this long timeStamp)
|
||||
{
|
||||
DateTime startTime = TimeZoneInfo.ConvertTime(new System.DateTime(1970, 1, 1), TimeZoneInfo.Local);
|
||||
DateTime result = startTime.AddSeconds(timeStamp);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 时间戳转换成时间
|
||||
/// </summary>
|
||||
/// <param name="timestamp">时间戳</param>
|
||||
/// <param name="millisecond">是否毫秒级,true毫秒级(默认值)</param>
|
||||
/// <param name="localTime">是否输出本地时间,true本地时间(默认值)</param>
|
||||
/// <returns></returns>
|
||||
public static DateTime? LoadFromUnixTimeStamp(this string timestamp)
|
||||
{
|
||||
if (long.TryParse(timestamp, out long ts))
|
||||
{
|
||||
return ts.LoadFromUnixTimeStamp();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 1970 到现在的秒数
|
||||
/// </summary>
|
||||
/// <param name="time"></param>
|
||||
/// <returns></returns>
|
||||
public static int TimestampFrom19700101(this DateTime time)
|
||||
{
|
||||
return (int)(time - new DateTime(1970, 01, 01)).TotalSeconds;
|
||||
}
|
||||
|
||||
|
||||
#region 获取日期、明天
|
||||
public static DateTime Date(this DateTime? time)
|
||||
{
|
||||
return Convert.ToDateTime(time).Date;
|
||||
}
|
||||
public static DateTime NextDate(this DateTime? time)
|
||||
{
|
||||
return Convert.ToDateTime(time).Date.AddDays(1);
|
||||
}
|
||||
public static DateTime Date(this DateTime time)
|
||||
{
|
||||
return time.Date;
|
||||
}
|
||||
public static DateTime NextDate(this DateTime time)
|
||||
{
|
||||
return time.Date.AddDays(1);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static DateTime Begin(this DateTime time)
|
||||
{
|
||||
return new DateTime(time.Year, time.Month, time.Day);
|
||||
}
|
||||
|
||||
public static DateTime End(this DateTime time)
|
||||
{
|
||||
return new DateTime(time.Year, time.Month, time.Day,23,59,59);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Dynamic;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
public static class DbDataReaderExtension
|
||||
{
|
||||
public static IDictionary<string, object> GetDataRow(this DbDataReader dataReader)
|
||||
{
|
||||
var dataRow = new ExpandoObject() as IDictionary<string, object>;
|
||||
|
||||
for (var iFiled = 0; iFiled < dataReader.FieldCount; iFiled++)
|
||||
{
|
||||
dataRow.Add(
|
||||
dataReader.GetName(iFiled),
|
||||
dataReader.IsDBNull(iFiled) ? "" : dataReader[iFiled]
|
||||
);
|
||||
}
|
||||
|
||||
return dataRow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
public static class EnumExtension
|
||||
{
|
||||
public static Dictionary<int, string> ToDictionary<T>()
|
||||
{
|
||||
Dictionary<int, string> dic = new Dictionary<int, string>();
|
||||
string namestr = "";
|
||||
foreach (var e in Enum.GetValues(typeof(T)))
|
||||
{
|
||||
namestr = "";
|
||||
|
||||
object[] objArrDisplay = e.GetType().GetField(e.ToString()).GetCustomAttributes(typeof(DisplayAttribute), true);//Display
|
||||
if (objArrDisplay.Any())
|
||||
{
|
||||
var da = objArrDisplay[0] as DisplayAttribute;
|
||||
namestr = da.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
object[] objArrDescription = e.GetType().GetField(e.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), true);//Description
|
||||
namestr = objArrDescription.Any() ? (objArrDescription[0] as DescriptionAttribute).Description : e.ToString();
|
||||
}
|
||||
int value = Convert.ToInt32(e);
|
||||
|
||||
|
||||
|
||||
// string str = item.GetDescription();
|
||||
// int value = (int) item;
|
||||
|
||||
dic.Add(value, namestr);
|
||||
}
|
||||
|
||||
return dic;
|
||||
}
|
||||
#region 获取枚举的相关信息的集合
|
||||
/// <summary>
|
||||
/// 获取枚举的相关信息的集合
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static List<EnumInfo> EnumToList<T>()
|
||||
{
|
||||
var list = new List<EnumInfo>();
|
||||
foreach (var e in Enum.GetValues(typeof(T)))
|
||||
{
|
||||
var m = new EnumInfo();
|
||||
object[] objArrDisplay = e.GetType().GetField(e.ToString()).GetCustomAttributes(typeof(DisplayAttribute), true);//Display
|
||||
if (objArrDisplay.Any())
|
||||
{
|
||||
var da = objArrDisplay[0] as DisplayAttribute;
|
||||
m.Name = da.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
object[] objArrDescription = e.GetType().GetField(e.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), true);//Description
|
||||
m.Name = objArrDescription.Any() ? (objArrDescription[0] as DescriptionAttribute).Description : e.ToString();
|
||||
}
|
||||
m.Value = Convert.ToInt32(e);
|
||||
list.Add(m);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
public class EnumInfo
|
||||
{
|
||||
public string Name { set; get; }
|
||||
|
||||
public int Value { set; get; }
|
||||
}
|
||||
#endregion
|
||||
public static string GetDisplayName<T>(T enumValue)
|
||||
{
|
||||
object[] objArrDisplay = enumValue.GetType().GetField(enumValue.ToString())
|
||||
?.GetCustomAttributes(typeof(DisplayAttribute), true);//Display
|
||||
if (objArrDisplay!=null&&objArrDisplay.Any())
|
||||
{
|
||||
var da = objArrDisplay[0] as DisplayAttribute;
|
||||
return da?.Name;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取枚举上通过DisplayName、Description或Display柱注的名称
|
||||
/// 优先级为DisplayName>Description>Display
|
||||
/// </summary>
|
||||
/// <param name="e">枚举值</param>
|
||||
/// <returns>枚举名称</returns>
|
||||
///
|
||||
public static string GetEnumDisplayName(this Enum e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Type t = e.GetType();
|
||||
FieldInfo fi = t.GetField(Enum.GetName(t, e));
|
||||
var dna = fi.GetCustomAttribute<DisplayNameAttribute>();
|
||||
if (dna != null)
|
||||
return dna.DisplayName;
|
||||
var da = fi.GetCustomAttribute<DescriptionAttribute>();
|
||||
if (da != null)
|
||||
return da.Description;
|
||||
var d = fi.GetCustomAttribute<DisplayAttribute>();
|
||||
if (d != null)
|
||||
return d.Name;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return "获取枚举"+e.GetType().FullName+"名称错误:"+ex.Message;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static string ToHtmlSelectOptions<T>()
|
||||
{
|
||||
var dic = ToDictionary<T>();
|
||||
|
||||
string str = "";
|
||||
|
||||
foreach (var key in dic.Keys)
|
||||
{
|
||||
str += "<option value=\"" + key + "\">" + dic[key] + "</option>";
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#region 判断值是否在枚举类型中存在
|
||||
|
||||
/// <summary>
|
||||
/// 判断值是否在枚举中存在
|
||||
/// </summary>
|
||||
/// <param name="enumValue">需要判断的参数</param>
|
||||
/// <param name="enumType">枚举类型</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsExist(this int enumValue, Type enumType)
|
||||
{
|
||||
return Enum.IsDefined(enumType, enumValue);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using TinyPinyin.Core;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
public static class ExceptionExtension
|
||||
{
|
||||
public static string GetInfo(this Exception ex)
|
||||
{
|
||||
var info = $"S:{ex.Source},M:{ex.Message},ST:{ex.StackTrace}-----";
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
info += ex.InnerException.GetInfo();
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
public static class HttpClientFactoryExtension
|
||||
{
|
||||
public static HttpClient CreateClient(this IHttpClientFactory factory, TimeSpan timeOut)
|
||||
{
|
||||
var client = factory.CreateClient();
|
||||
|
||||
client.Timeout = timeOut;
|
||||
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
||||
public static class HttpClientExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// post请求,ContentType:application/json
|
||||
/// </summary>
|
||||
/// <param name="httpClient"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<HttpResponseMessage> PostAsJson(this HttpClient httpClient, string path, object data,
|
||||
Encoding encoding = null)
|
||||
{
|
||||
if (encoding == null)
|
||||
{
|
||||
encoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
string content = "";
|
||||
|
||||
if (data is string s)
|
||||
{
|
||||
content = s;
|
||||
}
|
||||
else
|
||||
{
|
||||
content = data.ToJson();
|
||||
}
|
||||
|
||||
HttpContent httpContent = new StringContent(content, encoding);
|
||||
|
||||
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||
|
||||
return await httpClient.PostAsync(path, httpContent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// post请求,ContentType:application/json
|
||||
/// </summary>
|
||||
/// <param name="httpClient"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> PostAsJsonGetString(this HttpClient httpClient, string path, object data,
|
||||
Encoding encoding = null)
|
||||
{
|
||||
var res = await httpClient.PostAsJson(path, data, encoding);
|
||||
|
||||
return await res.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
public static async Task<HttpResponseMessage> PostAsForm(this HttpClient httpClient, string path, IEnumerable<KeyValuePair<string, string>> data,
|
||||
Encoding encoding = null)
|
||||
{
|
||||
if (encoding == null)
|
||||
{
|
||||
encoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
HttpContent httpContent = new FormUrlEncodedContent(data);
|
||||
|
||||
return await httpClient.PostAsync(path, httpContent);
|
||||
}
|
||||
public static async Task<string> PostAsFormGetString(this HttpClient httpClient, string path, IEnumerable<KeyValuePair<string, string>> data,
|
||||
Encoding encoding = null)
|
||||
{
|
||||
var resp=await httpClient.PostAsForm(path, data, encoding);
|
||||
|
||||
return await resp.Content.ReadAsStringAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
public static class ListExtension
|
||||
{
|
||||
public static bool NullOrEmpty<T>(this IList<T> list)
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!list.Any())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#region 转换几个中所有元素的类型
|
||||
/// <summary>
|
||||
/// 转换几个中所有元素的类型
|
||||
/// </summary>
|
||||
/// <typeparam name="TO"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
/// <returns></returns>
|
||||
public static List<TO> ConvertListType<TO, T>(this List<T> list)
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
List<TO> newlist = new List<TO>();
|
||||
foreach (T t in list)
|
||||
{
|
||||
newlist.Add((TO)Convert.ChangeType(t, typeof(TO)));
|
||||
}
|
||||
return newlist;
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 添加
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static List<T> AddNew<T>(this List<T> list, T item)
|
||||
{
|
||||
list.Add(item);
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加多个集合
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static List<T> AddNewMult<T>(this List<T> list, List<T> item)
|
||||
{
|
||||
list.AddRange(item);
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static List<T> RemoveNew<T>(this List<T> list, T item)
|
||||
{
|
||||
list.Remove(item);
|
||||
return list;
|
||||
}
|
||||
|
||||
#region 按条件移除
|
||||
|
||||
/// <summary>
|
||||
/// 移除单条符合条件的数据
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="condtion">条件</param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static List<T> RemoveNew<T>(this List<T> list, Func<T, bool> condtion)
|
||||
{
|
||||
List<T> listTemp = list;
|
||||
var item = listTemp.FirstOrDefault(condtion);
|
||||
if (item != null)
|
||||
{
|
||||
listTemp.Remove(item);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除多条满足条件
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
/// <param name="condtion">条件</param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static List<T> RemoveMultNew<T>(this List<T> list, Func<T, bool> condtion)
|
||||
{
|
||||
List<T> listTemp = list;
|
||||
var items = listTemp.Where(condtion).ToList() ?? new List<T>();
|
||||
foreach (var item in items)
|
||||
{
|
||||
listTemp.Remove(item);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
public static class ListForEachExtension
|
||||
{
|
||||
public static async Task ForEachAsync<T>(this IEnumerable<T> list, Func<T, Task> func)
|
||||
{
|
||||
foreach (T value in list)
|
||||
{
|
||||
await func(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
public static class NumberExtension
|
||||
{
|
||||
public static int ToInt(this int? num)
|
||||
{
|
||||
if (num == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Convert.ToInt32(num);
|
||||
}
|
||||
|
||||
public static int ToInt(this JToken obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int.TryParse(obj.ToString(), out var num);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
public static decimal ToDecimal(this decimal? num)
|
||||
{
|
||||
if (num == null)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Convert.ToDecimal(num);
|
||||
}
|
||||
|
||||
public static long ToLong(this long? num)
|
||||
{
|
||||
if (num == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (long) num;
|
||||
}
|
||||
|
||||
public static int ToInt(this bool flag)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
using Nelibur.ObjectMapper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
public static class ObjectExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 将对象[主要是匿名对象]转换为dynamic
|
||||
/// </summary>
|
||||
public static dynamic ToDynamic(this object obj, decimal defaultVal)
|
||||
{
|
||||
decimal result;
|
||||
if (obj != null)
|
||||
if (decimal.TryParse(obj.ToString(), out result))
|
||||
return result;
|
||||
else
|
||||
return defaultVal;
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
// This extension method is broken out so you can use a similar pattern with
|
||||
// other MetaData elements in the future. This is your base method for each.
|
||||
public static T GetAttribute<T>(this object value) where T : Attribute
|
||||
{
|
||||
var type = value.GetType();
|
||||
var memberInfo = type.GetMember(value.ToString());
|
||||
if (!memberInfo.Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false);
|
||||
return (T) attributes[0];
|
||||
}
|
||||
|
||||
// This method creates a specific call to the above method, requesting the
|
||||
// Description MetaData attribute.
|
||||
public static string GetDescription(this object value)
|
||||
{
|
||||
var desAttribute = value.GetAttribute<DescriptionAttribute>();
|
||||
if (desAttribute != null)
|
||||
{
|
||||
return desAttribute.Description;
|
||||
}
|
||||
|
||||
var displayAttribute = value.GetAttribute<DisplayAttribute>();
|
||||
if (displayAttribute != null)
|
||||
{
|
||||
return displayAttribute.Name ?? displayAttribute.Description;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
#region 得到枚举字典(key对应枚举的值,value对应枚举的注释)
|
||||
|
||||
/// <summary>
|
||||
/// 得到枚举字典(key对应枚举的值,value对应枚举的注释)
|
||||
/// </summary>
|
||||
/// <typeparam name="TEnum"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<Enum, string> ToDescriptionDictionary<TEnum>()
|
||||
{
|
||||
Array values = Enum.GetValues(typeof(TEnum));
|
||||
Dictionary<Enum, string> nums = new Dictionary<Enum, string>();
|
||||
foreach (Enum value in values)
|
||||
{
|
||||
nums.Add(value, GetDescription(value));
|
||||
}
|
||||
|
||||
return nums;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 实体中string属性执行Trim()
|
||||
/// <summary>
|
||||
/// 对象string属性执行Trim()
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="t"></param>
|
||||
/// <returns></returns>
|
||||
public static T ObjectStrTrim<T>(this T t) where T:new ()
|
||||
{
|
||||
if (t != null)
|
||||
{
|
||||
foreach (var pi in t.GetType().GetProperties())
|
||||
{
|
||||
if (pi.PropertyType.Equals(typeof(string)) && pi.GetValue(t, null) != null)//判断属性的类型是不是String
|
||||
{
|
||||
pi.SetValue(t, pi.GetValue(t, null).ToString().Trim(), null);//给泛型的属性赋值
|
||||
}
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region
|
||||
public static T save<T>(this T obj,string key) where T:class,new()
|
||||
{
|
||||
Dictionary<string, object> dic = c.Value ?? new Dictionary<string, object>();
|
||||
dic.Add(key,obj);
|
||||
c.Value = dic;
|
||||
return obj;
|
||||
}
|
||||
public static AsyncLocal<Dictionary<string,Object>> c=new AsyncLocal<Dictionary<string, Object>>();
|
||||
#endregion
|
||||
|
||||
#region 对象转换
|
||||
|
||||
public static T MapTo<T>(this Object model)
|
||||
{
|
||||
var productDto = TinyMapper.Map<T>(model);
|
||||
|
||||
return productDto;
|
||||
}
|
||||
public static IEnumerable<T> MapsTo<T>(this Object model)
|
||||
{
|
||||
var generic = model.GetType().GetGenericTypeDefinition();
|
||||
|
||||
if (generic == typeof(List<>))
|
||||
{
|
||||
return TinyMapper.Map<List<T>>(model);
|
||||
}
|
||||
if (generic == typeof(Collection<>))
|
||||
{
|
||||
return TinyMapper.Map<Collection<T>>(model);
|
||||
}
|
||||
|
||||
throw new Exception("不合法的转换");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
|
||||
public static class RequestExtension
|
||||
{
|
||||
public static string Get(this HttpRequest request, string key)
|
||||
{
|
||||
if (request.Query.ContainsKey(key))
|
||||
{
|
||||
return request.Query[key];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
public static int GetInt(this HttpRequest request, string key)
|
||||
{
|
||||
if (request.Query.ContainsKey(key))
|
||||
{
|
||||
return Convert.ToInt32(request.Query[key]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static string GetUrl(this HttpRequest request, bool full=true)
|
||||
{
|
||||
if (full)
|
||||
{
|
||||
return $"{request.Scheme}://{request.Host}{request.Path}{request.QueryString}";
|
||||
}
|
||||
return $"{request.Path}{request.QueryString}";
|
||||
}
|
||||
|
||||
public static string Remove(this HttpRequest request, string key)
|
||||
{
|
||||
var q = request.Query.Where(m => !m.Key.Equals(key, StringComparison.InvariantCultureIgnoreCase));
|
||||
var kvs = q.Select(m => $"{m.Key}={m.Value}");
|
||||
return string.Join("&", kvs);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
public static class StreamExtension
|
||||
{
|
||||
public async static Task<string> ReadAsStringAsync(this Stream stream)
|
||||
{
|
||||
var reader = new StreamReader(stream);
|
||||
return await reader.ReadToEndAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,779 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using TinyPinyin.Core;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
public static class StringExtension
|
||||
{
|
||||
#region Url、Html编码
|
||||
|
||||
[DebuggerStepThrough]
|
||||
public static string UrlEncode(this string target)
|
||||
{
|
||||
return HttpUtility.UrlEncode(target);
|
||||
}
|
||||
|
||||
[DebuggerStepThrough]
|
||||
public static string UrlEncode(this string target, Encoding encoding)
|
||||
{
|
||||
return HttpUtility.UrlEncode(target, encoding);
|
||||
}
|
||||
|
||||
[DebuggerStepThrough]
|
||||
public static string UrlDecode(this string target)
|
||||
{
|
||||
return HttpUtility.UrlDecode(target);
|
||||
}
|
||||
|
||||
[DebuggerStepThrough]
|
||||
public static string UrlDecode(this string target, Encoding encoding)
|
||||
{
|
||||
return HttpUtility.UrlDecode(target, encoding);
|
||||
}
|
||||
|
||||
[DebuggerStepThrough]
|
||||
public static string AttributeEncode(this string target)
|
||||
{
|
||||
return HttpUtility.HtmlAttributeEncode(target);
|
||||
}
|
||||
|
||||
[DebuggerStepThrough]
|
||||
public static string HtmlEncode(this string target)
|
||||
{
|
||||
return HttpUtility.HtmlEncode(target);
|
||||
}
|
||||
|
||||
[DebuggerStepThrough]
|
||||
public static string HtmlDecode(this string target)
|
||||
{
|
||||
return HttpUtility.HtmlDecode(target);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unicode编码
|
||||
|
||||
/// <summary>
|
||||
/// 汉字转换为Unicode编码
|
||||
/// </summary>
|
||||
/// <param name="str">要编码的汉字字符串</param>
|
||||
/// <returns>Unicode编码的的字符串</returns>
|
||||
public static string ToUnicode(this string str)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
StringBuilder unicode = new StringBuilder();
|
||||
|
||||
foreach (char chr in str)
|
||||
{
|
||||
// Get the integral value of the character.
|
||||
int value = Convert.ToInt32(chr);
|
||||
// Convert the decimal value to a hexadecimal value in string form.
|
||||
string hexOutput = String.Format("{0:x}", value);
|
||||
|
||||
unicode.Append("\\u" + hexOutput);
|
||||
}
|
||||
|
||||
return unicode.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将Unicode编码转换为汉字字符串
|
||||
/// </summary>
|
||||
/// <param name="str">Unicode编码字符串</param>
|
||||
/// <returns>汉字字符串</returns>
|
||||
public static string FromUnicode(this string unicode)
|
||||
{
|
||||
if (string.IsNullOrEmpty(unicode))
|
||||
{
|
||||
return unicode;
|
||||
}
|
||||
|
||||
StringBuilder str = new StringBuilder();
|
||||
|
||||
unicode = unicode.Replace("\\u", "_");
|
||||
|
||||
string[] hex = unicode.Split('_');
|
||||
|
||||
for (int i = 1; i < hex.Length; i++)
|
||||
{
|
||||
int data = Convert.ToInt32(hex[i].ToString(), 16);
|
||||
|
||||
str.Append((char) data);
|
||||
}
|
||||
|
||||
return str.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 清除脚本
|
||||
|
||||
/// <summary>
|
||||
/// 清除脚本
|
||||
/// </summary>
|
||||
/// <param name="Htmlstring"></param>
|
||||
/// <returns></returns>
|
||||
public static string NoHTML(this string Htmlstring)
|
||||
{
|
||||
//删除脚本
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"<script[^>]*?>.*?</script>", "", RegexOptions.IgnoreCase);
|
||||
//删除HTML
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"<.*?>|&.{4,5}", "", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"-->", "", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"<!--.*", "", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"&(quot|#34);", "\"", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"&(nbsp|#160);", " ", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"&(iexcl|#161);", "\xa1", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"&(cent|#162);", "\xa2", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"&(pound|#163);", "\xa3", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"&(copy|#169);", "\xa9", RegexOptions.IgnoreCase);
|
||||
Htmlstring = Regex.Replace(Htmlstring, @"&#(\d+);", "", RegexOptions.IgnoreCase);
|
||||
Htmlstring.Replace("<", "");
|
||||
Htmlstring.Replace(">", "");
|
||||
Htmlstring.Replace("\r\n", "");
|
||||
Htmlstring = Htmlstring.HtmlEncode().Trim();
|
||||
return Htmlstring;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 清楚小数点后的0
|
||||
|
||||
/// <summary>
|
||||
/// 清楚小数点后的0
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static string DecimalToInt(this string str)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str))
|
||||
return "0";
|
||||
str = float.Parse(str).ToString("0.00");
|
||||
if (Int32.Parse(str.Substring(str.IndexOf(".") + 1)) == 0)
|
||||
{
|
||||
return str.Substring(0, str.IndexOf("."));
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
public static string ToMoney(this decimal num)
|
||||
{
|
||||
return num.ToString("0.00");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转换成百分比
|
||||
|
||||
/// <summary>
|
||||
/// 转换百分比
|
||||
/// </summary>
|
||||
/// <param name="num"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToP2(this decimal num)
|
||||
{
|
||||
string str = num.ToString("0.00").TrimEnd('0');
|
||||
|
||||
if (str.EndsWith("."))
|
||||
{
|
||||
str = str.Replace(".", "");
|
||||
}
|
||||
|
||||
return str + "%";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 汉字转拼音缩写
|
||||
|
||||
/// <summary>
|
||||
/// 汉字转拼音缩写
|
||||
/// <returns>拼音缩写</returns>
|
||||
public static string GetPYString(this string str)
|
||||
{
|
||||
string tempStr = "";
|
||||
foreach (char c in str)
|
||||
{
|
||||
if ((int) c >= 33 && (int) c <= 126)
|
||||
{
|
||||
//字母和符号原样保留
|
||||
|
||||
tempStr += c.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
//累加拼音声母
|
||||
tempStr += PinyinHelper.GetPinyin(c).ToCharArray()[0];
|
||||
}
|
||||
}
|
||||
|
||||
return tempStr;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 清楚字符串中所有空格,包括\r\n\t
|
||||
|
||||
/// <summary>
|
||||
/// 清楚字符串中所有空格,包括\r\n\t
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static string CleanSpace(this string str)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str))
|
||||
return string.Empty;
|
||||
return Regex.Replace(str, @"\s", "");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 反转义
|
||||
|
||||
/// <summary>
|
||||
/// 反转义
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static string Unescape(this string str)
|
||||
{
|
||||
return System.Text.RegularExpressions.Regex.Unescape(str);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 转换成数字
|
||||
|
||||
public static int ToInt(this string str)
|
||||
{
|
||||
int i = 0;
|
||||
int.TryParse(str, out i);
|
||||
return i;
|
||||
}
|
||||
|
||||
public static decimal ToDecimal(this string str)
|
||||
{
|
||||
decimal i = 0;
|
||||
decimal.TryParse(str, out i);
|
||||
return i;
|
||||
}
|
||||
|
||||
public static int ToInt(this string str, int defaultnum = 0)
|
||||
{
|
||||
int i;
|
||||
bool flag = Int32.TryParse(str, out i);
|
||||
if (flag)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultnum;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转为double类型
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static double ToDouble(this string str)
|
||||
{
|
||||
double result = 0;
|
||||
double.TryParse(str, out result);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 返回字符串真实长度, 1个汉字长度为2
|
||||
|
||||
/// <summary>
|
||||
/// 返回字符串真实长度, 1个汉字长度为2
|
||||
/// </summary>
|
||||
/// <returns>字符长度</returns>
|
||||
public static int GetStringLength(this string str)
|
||||
{
|
||||
return Encoding.Default.GetBytes(str).Length;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 从字符串的指定位置截取指定长度的子字符串
|
||||
|
||||
/// <summary>
|
||||
/// 从字符串的指定位置截取指定长度的子字符串
|
||||
/// </summary>
|
||||
/// <param name="str">原字符串</param>
|
||||
/// <param name="startIndex">子字符串的起始位置</param>
|
||||
/// <param name="length">子字符串的长度</param>
|
||||
/// <returns>子字符串</returns>
|
||||
public static string CutString(this string str, int startIndex, int length)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
if (startIndex >= 0)
|
||||
{
|
||||
if (length < 0)
|
||||
{
|
||||
length = length * -1;
|
||||
if (startIndex - length < 0)
|
||||
{
|
||||
length = startIndex;
|
||||
startIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
startIndex = startIndex - length;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (startIndex > str.Length)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (length < 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (length + startIndex > 0)
|
||||
{
|
||||
length = length + startIndex;
|
||||
startIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (str.Length - startIndex < length)
|
||||
{
|
||||
length = str.Length - startIndex;
|
||||
}
|
||||
|
||||
return str.Substring(startIndex, length);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 判断文件名是否为浏览器可以直接显示的图片文件名
|
||||
|
||||
/// <summary>
|
||||
/// 判断文件名是否为浏览器可以直接显示的图片文件名
|
||||
/// </summary>
|
||||
/// <param name="filename">文件名</param>
|
||||
/// <returns>是否可以直接显示</returns>
|
||||
public static bool IsImgFilename(this string filename)
|
||||
{
|
||||
filename = filename.Trim();
|
||||
if (filename.EndsWith(".") || filename.IndexOf(".") == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string extname = filename.Substring(filename.LastIndexOf(".") + 1).ToLower();
|
||||
return (extname == "jpg" || extname == "jpeg" || extname == "png" || extname == "bmp" || extname == "gif");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 取指定长度的字符串
|
||||
|
||||
public static string GetUnicodeSubString(this string str, int len, string p_TailString)
|
||||
{
|
||||
string result = string.Empty; // 最终返回的结果
|
||||
int byteLen = System.Text.Encoding.Default.GetByteCount(str); // 单字节字符长度
|
||||
int charLen = str.Length; // 把字符平等对待时的字符串长度
|
||||
int byteCount = 0; // 记录读取进度
|
||||
int pos = 0; // 记录截取位置
|
||||
if (byteLen > len)
|
||||
{
|
||||
for (int i = 0; i < charLen; i++)
|
||||
{
|
||||
if (Convert.ToInt32(str.ToCharArray()[i]) > 255) // 按中文字符计算加2
|
||||
byteCount += 2;
|
||||
else // 按英文字符计算加1
|
||||
byteCount += 1;
|
||||
if (byteCount > len) // 超出时只记下上一个有效位置
|
||||
{
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
else if (byteCount == len) // 记下当前位置
|
||||
{
|
||||
pos = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos >= 0)
|
||||
result = str.Substring(0, pos) + p_TailString;
|
||||
}
|
||||
else
|
||||
result = str;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取指定长度的字符串
|
||||
/// </summary>
|
||||
/// <param name="p_SrcString">要检查的字符串</param>
|
||||
/// <param name="p_StartIndex">起始位置</param>
|
||||
/// <param name="p_Length">指定长度</param>
|
||||
/// <param name="p_TailString">用于替换的字符串</param>
|
||||
/// <returns>截取后的字符串</returns>
|
||||
public static string GetSubString(this string p_SrcString, int p_StartIndex, int p_Length, string p_TailString)
|
||||
{
|
||||
string myResult = p_SrcString;
|
||||
|
||||
Byte[] bComments = Encoding.UTF8.GetBytes(p_SrcString);
|
||||
foreach (char c in Encoding.UTF8.GetChars(bComments))
|
||||
{
|
||||
//当是日文或韩文时(注:中文的范围:\u4e00 - \u9fa5, 日文在\u0800 - \u4e00, 韩文为\xAC00-\xD7A3)
|
||||
if ((c > '\u0800' && c < '\u4e00') || (c > '\xAC00' && c < '\xD7A3'))
|
||||
{
|
||||
//if (System.Text.RegularExpressions.Regex.IsMatch(p_SrcString, "[\u0800-\u4e00]+") || System.Text.RegularExpressions.Regex.IsMatch(p_SrcString, "[\xAC00-\xD7A3]+"))
|
||||
//当截取的起始位置超出字段串长度时
|
||||
if (p_StartIndex >= p_SrcString.Length)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
else
|
||||
{
|
||||
return p_SrcString.Substring(p_StartIndex,
|
||||
((p_Length + p_StartIndex) > p_SrcString.Length)
|
||||
? (p_SrcString.Length - p_StartIndex)
|
||||
: p_Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (p_Length >= 0)
|
||||
{
|
||||
byte[] bsSrcString = Encoding.Default.GetBytes(p_SrcString);
|
||||
|
||||
//当字符串长度大于起始位置
|
||||
if (bsSrcString.Length > p_StartIndex)
|
||||
{
|
||||
int p_EndIndex = bsSrcString.Length;
|
||||
|
||||
//当要截取的长度在字符串的有效长度范围内
|
||||
if (bsSrcString.Length > (p_StartIndex + p_Length))
|
||||
{
|
||||
p_EndIndex = p_Length + p_StartIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
//当不在有效范围内时,只取到字符串的结尾
|
||||
|
||||
p_Length = bsSrcString.Length - p_StartIndex;
|
||||
p_TailString = "";
|
||||
}
|
||||
|
||||
|
||||
int nRealLength = p_Length;
|
||||
int[] anResultFlag = new int[p_Length];
|
||||
byte[] bsResult = null;
|
||||
|
||||
int nFlag = 0;
|
||||
for (int i = p_StartIndex; i < p_EndIndex; i++)
|
||||
{
|
||||
if (bsSrcString[i] > 127)
|
||||
{
|
||||
nFlag++;
|
||||
if (nFlag == 3)
|
||||
{
|
||||
nFlag = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nFlag = 0;
|
||||
}
|
||||
|
||||
anResultFlag[i] = nFlag;
|
||||
}
|
||||
|
||||
if ((bsSrcString[p_EndIndex - 1] > 127) && (anResultFlag[p_Length - 1] == 1))
|
||||
{
|
||||
nRealLength = p_Length + 1;
|
||||
}
|
||||
|
||||
bsResult = new byte[nRealLength];
|
||||
|
||||
Array.Copy(bsSrcString, p_StartIndex, bsResult, 0, nRealLength);
|
||||
|
||||
myResult = Encoding.Default.GetString(bsResult);
|
||||
|
||||
myResult = myResult + p_TailString;
|
||||
}
|
||||
}
|
||||
|
||||
return myResult;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 自定义的替换字符串函数
|
||||
|
||||
/// <summary>
|
||||
/// 自定义的替换字符串函数
|
||||
/// </summary>
|
||||
public static string ReplaceString(string SourceString, string SearchString, string ReplaceString,
|
||||
bool IsCaseInsensetive)
|
||||
{
|
||||
return Regex.Replace(SourceString, Regex.Escape(SearchString), ReplaceString,
|
||||
IsCaseInsensetive ? RegexOptions.IgnoreCase : RegexOptions.None);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 检测是否符合email格式
|
||||
|
||||
/// <summary>
|
||||
/// 检测是否符合email格式
|
||||
/// </summary>
|
||||
/// <param name="strEmail">要判断的email字符串</param>
|
||||
/// <returns>判断结果</returns>
|
||||
public static bool IsValidEmail(this string strEmail)
|
||||
{
|
||||
return Regex.IsMatch(strEmail,
|
||||
@"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 检测是否是正确的Url
|
||||
|
||||
/// <summary>
|
||||
/// 检测是否是正确的Url
|
||||
/// </summary>
|
||||
/// <param name="strUrl">要验证的Url</param>
|
||||
/// <returns>判断结果</returns>
|
||||
public static bool IsURL(this string strUrl)
|
||||
{
|
||||
return Regex.IsMatch(strUrl,
|
||||
@"^(http|https)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{1,10}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 是否为ip
|
||||
|
||||
/// <summary>
|
||||
/// 是否为ip
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsIP(this string ip)
|
||||
{
|
||||
return Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 是否为手机号
|
||||
|
||||
/// <summary>
|
||||
/// 是否为手机号
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsMobilePhone(this string str)
|
||||
{
|
||||
return Regex.IsMatch(str, @"^0?(13[0-9]|15[0-9]|166|17[0-9]|18[0-9]|19[8-9]|14[5-7])[0-9]{8}$");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 是否为身份证号
|
||||
|
||||
/// <summary>
|
||||
/// 是否为身份证号
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsIdCard(this string str)
|
||||
{
|
||||
return Regex.IsMatch(str, @"(^\d{15}$)|(^\d{17}([0-9]|X)$)");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 是否为小数
|
||||
|
||||
/// <summary>
|
||||
/// 是否为小数
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsPositiveNumber(this string str)
|
||||
{
|
||||
return Regex.IsMatch(str, @"^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 是否为数字
|
||||
|
||||
/// <summary>
|
||||
/// 是否为数字
|
||||
/// </summary>
|
||||
/// <param name="str"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsNumber(this string str)
|
||||
{
|
||||
return Regex.IsMatch(str, @"^[+-]?\d*[.]?\d*$");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 字符串转化为泛型集合
|
||||
|
||||
/// <summary>
|
||||
/// 字符串转化为泛型集合
|
||||
/// </summary>
|
||||
/// <param name="str">字符串</param>
|
||||
/// <param name="splitstr">要分割的字符</param>
|
||||
/// <returns></returns>
|
||||
public static List<T> StrToList<T>(this string str, char splitstr)
|
||||
{
|
||||
List<T> list = new List<T>();
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
string[] strarray = str.Split(new Char[] {splitstr}, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
foreach (string s in strarray)
|
||||
{
|
||||
if (s != "")
|
||||
list.Add((T) Convert.ChangeType(s, typeof(T)));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字符串转化为泛型集合
|
||||
/// </summary>
|
||||
/// <param name="str">字符串</param>
|
||||
/// <returns></returns>
|
||||
public static List<T> StrToList<T>(this string str)
|
||||
{
|
||||
return StrToList<T>(str, ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static string ToGBK(this string str)
|
||||
{
|
||||
return Encoding.GetEncoding("GBK").GetString(Encoding.Default.GetBytes(str));
|
||||
}
|
||||
|
||||
public static string FromGBK(this string str)
|
||||
{
|
||||
return Encoding.Default.GetString(Encoding.GetEncoding("GBK").GetBytes(str));
|
||||
}
|
||||
|
||||
public static string ToBase64String(this string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(value);
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
|
||||
public static string FromBase64String(this string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
byte[] bytes = Convert.FromBase64String(value);
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
|
||||
|
||||
public static string RegexMatch(this string str, string pattern)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Regex.Match(str, pattern, RegexOptions.IgnoreCase | RegexOptions.Multiline).Value;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static List<string> RegexMatches(this string str, string pattern)
|
||||
{
|
||||
List<string> list = new List<string>();
|
||||
|
||||
try
|
||||
{
|
||||
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||||
|
||||
if (regex.IsMatch(str))
|
||||
{
|
||||
MatchCollection matchCollection = regex.Matches(str);
|
||||
|
||||
foreach (Match match in matchCollection)
|
||||
{
|
||||
list.Add(match.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Has(this string str)
|
||||
{
|
||||
return !string.IsNullOrEmpty(str?.Trim());
|
||||
}
|
||||
public static bool NotHas(this string str)
|
||||
{
|
||||
return string.IsNullOrEmpty(str?.Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using Nelibur.ObjectMapper;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Hncore.Infrastructure.Extension
|
||||
{
|
||||
public static class TinyMapperExtension
|
||||
{
|
||||
public static void Binds<T1, T2>()
|
||||
{
|
||||
TinyMapper.Bind<T1, T2>();
|
||||
TinyMapper.Bind<T2, T1>();
|
||||
|
||||
TinyMapper.Bind<List<T1>, List<T2>>();
|
||||
TinyMapper.Bind<List<T2>, List<T1>>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!--<TargetFramework>netcoreapp2.2</TargetFramework>-->
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="aliyun-net-sdk-core" Version="1.5.3" />
|
||||
<PackageReference Include="AngleSharp" Version="0.12.1" />
|
||||
<PackageReference Include="Autofac" Version="4.9.1" />
|
||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.4.0" />
|
||||
<PackageReference Include="Bogus" Version="26.0.1" />
|
||||
<PackageReference Include="CSRedisCore" Version="3.0.60" />
|
||||
<PackageReference Include="Dapper" Version="1.60.6" />
|
||||
<PackageReference Include="DotNetCore.NPOI" Version="1.2.1" />
|
||||
<PackageReference Include="JWT" Version="5.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.2.0" />
|
||||
<PackageReference Include="MQiniu.Core" Version="1.0.1" />
|
||||
<PackageReference Include="MySqlConnector" Version="0.56.0" />
|
||||
<PackageReference Include="NLog.Extensions.Logging" Version="1.4.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="4.0.1" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="4.5.1" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.1" />
|
||||
<PackageReference Include="TinyMapper" Version="3.0.2-beta" />
|
||||
<PackageReference Include="TinyPinyin.Core.Standard" Version="1.0.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
|
||||
<PackageReference Include="MQTTnet" Version="2.8.5" />
|
||||
<PackageReference Include="Polly" Version="7.1.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="nlog.config">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Hncore.Infrastructure.IOC
|
||||
{
|
||||
public interface IDependency
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Hncore.Infrastructure.IOC
|
||||
{
|
||||
public interface IPerRequest
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Hncore.Infrastructure.IOC
|
||||
{
|
||||
public interface ISingleInstance
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using MQTTnet;
|
||||
using MQTTnet.Client;
|
||||
using Polly;
|
||||
|
||||
namespace Hncore.Infrastructure.Mqtt
|
||||
{
|
||||
public class MQTTClient : IDisposable
|
||||
{
|
||||
//实例 ID,购买后从控制台获取
|
||||
string _instanceId = "post-cn-v0h12xbue09";
|
||||
|
||||
//此处填写购买得到的 MQTT 接入点域名
|
||||
string _brokerUrl = "post-cn-v0h12xbue09.mqtt.aliyuncs.com";
|
||||
|
||||
//此处填写阿里云帐号 AccessKey
|
||||
string _accessKey = "LTAIaJpHI68JfX2c";
|
||||
|
||||
//此处填写阿里云帐号 SecretKey
|
||||
string _secretKey = "f17za6FRggVzwlSqzFHl8GndQ59SGV";
|
||||
|
||||
//此处填写客户端 ClientId,需要保证全局唯一,其中前缀部分即 GroupId 需要先在 MQ 控制台创建
|
||||
string _clientId = "GID_DOOR@@@MA_" + Guid.NewGuid();
|
||||
|
||||
private IMqttClient _mqttClient;
|
||||
|
||||
private SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
|
||||
|
||||
private ConcurrentDictionary<string, Action<string>> cmdMap = new ConcurrentDictionary<string, Action<string>>();
|
||||
|
||||
public MQTTClient()
|
||||
{
|
||||
_mqttClient = new MqttFactory().CreateMqttClient();
|
||||
|
||||
_mqttClient.Disconnected += async (s, e) =>
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(2));
|
||||
await Conn();
|
||||
};
|
||||
_mqttClient.ApplicationMessageReceived += (s, e) =>
|
||||
{
|
||||
var topic = e.ApplicationMessage.Topic.TrimEnd('/');
|
||||
var data = Encoding.UTF8.GetString(e.ApplicationMessage.Payload??new byte[0]);
|
||||
Console.WriteLine("### RECEIVED APPLICATION MESSAGE ###");
|
||||
Console.WriteLine($"+ Topic = {topic}");
|
||||
Console.WriteLine($"+ Payload = {data}");
|
||||
Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");
|
||||
Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}");
|
||||
Console.WriteLine();
|
||||
if (cmdMap.ContainsKey(topic))
|
||||
{
|
||||
try
|
||||
{
|
||||
cmdMap[topic](data);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error($"Mqtt:{topic}", ex.Message);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private async Task Conn()
|
||||
{
|
||||
if (!_mqttClient.IsConnected)
|
||||
{
|
||||
await _lock.WaitAsync();
|
||||
|
||||
try
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
await Policy.Handle<Exception>()
|
||||
.OrResult<MqttClientConnectResult>(res => !res.IsSessionPresent)
|
||||
.RetryAsync(10)
|
||||
.ExecuteAsync(async () =>
|
||||
{
|
||||
if (!_mqttClient.IsConnected)
|
||||
{
|
||||
i++;
|
||||
|
||||
try
|
||||
{
|
||||
string userName = "Signature|" + _accessKey + "|" + _instanceId;
|
||||
string passWord = HMACSHA1(_secretKey, _clientId);
|
||||
|
||||
var options = new MqttClientOptionsBuilder()
|
||||
.WithClientId(_clientId)
|
||||
.WithTcpServer(_brokerUrl)
|
||||
.WithCredentials(userName, passWord)
|
||||
.WithCleanSession()
|
||||
.Build();
|
||||
|
||||
return await _mqttClient.ConnectAsync(options);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogHelper.Error($"mqtt连接失败,第{i}次连接", e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return new MqttClientConnectResult(true);
|
||||
});
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task PublishAsync(string topic, string payload)
|
||||
{
|
||||
await Conn();
|
||||
|
||||
await _mqttClient.PublishAsync(topic, payload);
|
||||
}
|
||||
|
||||
public async Task SubscribeAsync(string topic, Action<string> action)
|
||||
{
|
||||
await Conn();
|
||||
var option = new TopicFilterBuilder().WithTopic(topic).Build();
|
||||
await _mqttClient.SubscribeAsync(option);
|
||||
cmdMap[topic] = action;
|
||||
}
|
||||
|
||||
public static string HMACSHA1(string key, string dataToSign)
|
||||
{
|
||||
Byte[] secretBytes = UTF8Encoding.UTF8.GetBytes(key);
|
||||
HMACSHA1 hmac = new HMACSHA1(secretBytes);
|
||||
Byte[] dataBytes = UTF8Encoding.UTF8.GetBytes(dataToSign);
|
||||
Byte[] calcHash = hmac.ComputeHash(dataBytes);
|
||||
String calcHashString = Convert.ToBase64String(calcHash);
|
||||
return calcHashString;
|
||||
}
|
||||
|
||||
public async void Dispose()
|
||||
{
|
||||
await _mqttClient.DisconnectAsync();
|
||||
_mqttClient?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Hncore.Infrastructure.OpenApi
|
||||
{
|
||||
/// <summary>
|
||||
/// 接入的应用
|
||||
/// </summary>
|
||||
public class Application
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用唯一标识
|
||||
/// </summary>
|
||||
public string AppId { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 应用密钥
|
||||
/// </summary>
|
||||
public string AppKey { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用
|
||||
/// </summary>
|
||||
public bool Enable { get; set; } = true;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Hncore.Infrastructure.Core.Web;
|
||||
|
||||
namespace Hncore.Infrastructure.OpenApi
|
||||
{
|
||||
public class OpenApiAuthAttribute : TypeFilterAttribute
|
||||
{
|
||||
public OpenApiAuthAttribute() : base(typeof(OpenApiAuthFilter))
|
||||
{
|
||||
Order = -9997;
|
||||
}
|
||||
}
|
||||
|
||||
public class OpenApiAuthFilter : IAsyncAuthorizationFilter
|
||||
{
|
||||
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
|
||||
{
|
||||
if (context.Filters.Any(item => item is IAllowAnonymousFilter))
|
||||
{
|
||||
context.HttpContext.Items["AllowAnonymous"] = true;
|
||||
return;
|
||||
}
|
||||
|
||||
context.HttpContext.Items["OpenApi"] = true;
|
||||
|
||||
var body = await context.HttpContext.Request.ReadBodyAsStringAsync();
|
||||
|
||||
var requestBase = body.FromJsonTo<OpenApiRequestBase>();
|
||||
|
||||
if (requestBase.Timestamp==null)
|
||||
{
|
||||
OpenApiException.Throw(OpenApiReturnCode.Error,"缺少timestamp参数");
|
||||
}
|
||||
|
||||
if (!requestBase.Sign.Has())
|
||||
{
|
||||
OpenApiException.Throw(OpenApiReturnCode.Error,"缺少sign参数");
|
||||
}
|
||||
|
||||
if (!requestBase.AppId.Has())
|
||||
{
|
||||
OpenApiException.Throw(OpenApiReturnCode.Error,"缺少appid参数");
|
||||
}
|
||||
|
||||
var application = await RedisHelper.HGetAsync<Application>("OpenApi:Application", requestBase.AppId);
|
||||
|
||||
context.HttpContext.Items["OpenApiAppKey"] = application.AppKey;
|
||||
|
||||
if (!application.Enable)
|
||||
{
|
||||
OpenApiException.Throw(OpenApiReturnCode.Unauthorized);
|
||||
}
|
||||
|
||||
if (DateTimeHelper.ToUnixTimestamp(DateTime.Now) - requestBase.Timestamp > 60)
|
||||
{
|
||||
OpenApiException.Throw(OpenApiReturnCode.TimeStampExpired);
|
||||
}
|
||||
|
||||
requestBase.CheckSign(application.AppKey);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Hncore.Infrastructure.OpenApi
|
||||
{
|
||||
public class OpenApiException: Exception
|
||||
{
|
||||
public OpenApiReturnCode Code { get; } = OpenApiReturnCode.InternalError;
|
||||
|
||||
public OpenApiException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public OpenApiException(OpenApiReturnCode code, string message = "") : base(message)
|
||||
{
|
||||
Code = code;
|
||||
}
|
||||
|
||||
public static void Throw(string message = "")
|
||||
{
|
||||
throw new OpenApiException(message);
|
||||
}
|
||||
|
||||
public static void Throw(OpenApiReturnCode code, string message = "")
|
||||
{
|
||||
throw new OpenApiException(code, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Hncore.Infrastructure.OpenApi
|
||||
{
|
||||
public class OpenApiRequestBase
|
||||
{
|
||||
[JsonProperty("appid")]
|
||||
public string AppId { get; set; }
|
||||
|
||||
[JsonProperty("timestamp")]
|
||||
public long? Timestamp { get; set; }
|
||||
|
||||
[JsonProperty("sign")]
|
||||
public string Sign { get; set; }
|
||||
|
||||
public void CheckSign(string key)
|
||||
{
|
||||
var sign = OpenApiSignUtil.CreateSign(this.Timestamp.ToLong(), key);
|
||||
|
||||
if (!String.Equals(sign, Sign, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
OpenApiException.Throw(OpenApiReturnCode.SignError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Extension;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Hncore.Infrastructure.OpenApi
|
||||
{
|
||||
public class OpenApiResult<T> where T : class, new()
|
||||
{
|
||||
[JsonProperty("code")] public OpenApiReturnCode Code { get; private set; }
|
||||
|
||||
[JsonProperty("message")] public string Message { get; private set; } = "";
|
||||
|
||||
[JsonProperty("timestamp")] public long Timestamp { get; set; }
|
||||
|
||||
[JsonProperty("sign")] public string Sign { get; set; }
|
||||
|
||||
[JsonProperty("data")] public T Data { get; set; } = new T();
|
||||
|
||||
private static readonly Dictionary<Enum, string> Dic;
|
||||
|
||||
static OpenApiResult()
|
||||
{
|
||||
Dic = ObjectExtension.ToDescriptionDictionary<OpenApiReturnCode>();
|
||||
}
|
||||
|
||||
|
||||
public OpenApiResult(OpenApiReturnCode code = OpenApiReturnCode.Success, string message = "")
|
||||
{
|
||||
Code = code;
|
||||
|
||||
if (string.IsNullOrEmpty(message) && Dic.ContainsKey(Code))
|
||||
{
|
||||
Message = Dic[Code];
|
||||
}
|
||||
else
|
||||
{
|
||||
Message = message;
|
||||
}
|
||||
|
||||
this.Timestamp = DateTimeHelper.ToUnixTimestamp(DateTime.Now);
|
||||
}
|
||||
|
||||
public void CreateSign(string key)
|
||||
{
|
||||
this.Sign = OpenApiSignUtil.CreateSign(this.Timestamp, key);
|
||||
}
|
||||
|
||||
public OpenApiResult<T> CreateSign(HttpContext httpContext)
|
||||
{
|
||||
var key = httpContext.Items["OpenApiAppKey"].ToString();
|
||||
|
||||
this.Sign = OpenApiSignUtil.CreateSign(this.Timestamp, key);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public class OpenApiResult : OpenApiResult<object>
|
||||
{
|
||||
public OpenApiResult(OpenApiReturnCode code = OpenApiReturnCode.Success, string message = "") : base(code,
|
||||
message)
|
||||
{
|
||||
}
|
||||
|
||||
public new OpenApiResult CreateSign(HttpContext httpContext)
|
||||
{
|
||||
var key = httpContext.Items["OpenApiAppKey"].ToString();
|
||||
|
||||
this.Sign = OpenApiSignUtil.CreateSign(this.Timestamp, key);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public enum OpenApiReturnCode
|
||||
{
|
||||
/// <summary>
|
||||
/// 成功
|
||||
/// </summary>
|
||||
[Description("成功")] Success = 10000,
|
||||
|
||||
/// <summary>
|
||||
/// 验签失败
|
||||
/// </summary>
|
||||
[Description("未授权")] Unauthorized = 40001,
|
||||
|
||||
/// <summary>
|
||||
/// 验签失败
|
||||
/// </summary>
|
||||
[Description("验签失败")] SignError = 40002,
|
||||
|
||||
/// <summary>
|
||||
/// 时间戳过期
|
||||
/// </summary>
|
||||
[Description("时间戳过期")] TimeStampExpired = 40003,
|
||||
|
||||
/// <summary>
|
||||
/// 内部错误
|
||||
/// </summary>
|
||||
[Description("内部错误")] InternalError = 50000,
|
||||
|
||||
/// <summary>
|
||||
/// 处理失败
|
||||
/// </summary>
|
||||
[Description("处理失败")] Error = 500001
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Data;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Hncore.Infrastructure.OpenApi
|
||||
{
|
||||
public static class OpenApiSignUtil
|
||||
{
|
||||
public static string CreateSign(long timestamp, string key)
|
||||
{
|
||||
return SecurityHelper.GetMd5Hash(timestamp.ToString() + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Dapper;
|
||||
using Hncore.Infrastructure.Common;
|
||||
using Hncore.Infrastructure.Serializer;
|
||||
using MySql.Data.MySqlClient;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Hncore.Infrastructure.OperationLog
|
||||
{
|
||||
public class OperationLog
|
||||
{
|
||||
/// <summary>
|
||||
/// 物业id
|
||||
/// </summary>
|
||||
[JsonProperty("owner_id")]
|
||||
public int OwnerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
[JsonProperty("createtime")]
|
||||
public DateTime CreateTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
[JsonProperty("updatetime")]
|
||||
public DateTime UpdateTime { get; set; } = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// 删除标记
|
||||
/// </summary>
|
||||
[JsonProperty("deletetag")]
|
||||
public int DeleteTag { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 创建人id
|
||||
/// </summary>
|
||||
[JsonProperty("creatorid")]
|
||||
public int CreatorId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新人id
|
||||
/// </summary>
|
||||
[JsonProperty("updatorid")]
|
||||
public int UpdatorId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作目标id
|
||||
/// </summary>
|
||||
[JsonProperty("targetid")]
|
||||
public int TargetId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作人名
|
||||
/// </summary>
|
||||
[JsonProperty("operator")]
|
||||
public string Operator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作说明
|
||||
/// </summary>
|
||||
[JsonProperty("opdesc")]
|
||||
public string OpDesc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作前
|
||||
/// </summary>
|
||||
[JsonProperty("beforeop")]
|
||||
public string BeforeOp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作后
|
||||
/// </summary>
|
||||
[JsonProperty("afterop")]
|
||||
public string AfterOp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作对象所在小区编码
|
||||
/// </summary>
|
||||
[JsonProperty("projectcode")]
|
||||
public int ProjectCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 小区名称
|
||||
/// </summary>
|
||||
[JsonProperty("estatename")]
|
||||
public string EstateName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作权限编码
|
||||
/// </summary>
|
||||
[JsonProperty("permissioncode")]
|
||||
public string PermissionCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作权限标签
|
||||
/// </summary>
|
||||
[JsonProperty("permissionlabel")]
|
||||
public string PermissionLabel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作菜单编码
|
||||
/// </summary>
|
||||
[JsonProperty("optype")]
|
||||
public int OpType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作菜单名称
|
||||
/// </summary>
|
||||
[JsonProperty("optypename")]
|
||||
public string OpTypeName { get; set; }
|
||||
|
||||
public void Write()
|
||||
{
|
||||
try
|
||||
{
|
||||
OperationLogStorage.WriteLog(this);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogHelper.Error("写操作日志失败", e);
|
||||
}
|
||||
}
|
||||
public void WriteAsync()
|
||||
{
|
||||
Task.Run(()=> Write());
|
||||
}
|
||||
}
|
||||
|
||||
internal class OperationLogStorage
|
||||
{
|
||||
private static string _devConn =
|
||||
"Server=rm-bp12e1533udh1827azo.mysql.rds.aliyuncs.com;Database=etor_property_test;User=etor_test;Password=etor_test!QAZ2wsx;Convert Zero Datetime=True;";
|
||||
|
||||
private static string _proConn =
|
||||
"Server=rm-bp1z48e1qz15k7q9qo.mysql.rds.aliyuncs.com;Database=etor_property_pro;User=sadmin;Password=!QAZ2wsx;Convert Zero Datetime=True;";
|
||||
|
||||
private static string _insertSql = @"INSERT INTO etor_property_operationlog
|
||||
(
|
||||
owner_id, createtime, updatetime, deletetag, creatorid, updatorid, targetid, operator, opdesc, beforeop, afterop, projectcode, estatename, permissioncode, permissionlabel, optype, optypename
|
||||
)
|
||||
VALUES (@OwnerId,@CreateTime,@UpdateTime,@DeleteTag,@CreatorId,@UpdatorId,@TargetId,@Operator,@OpDesc,@BeforeOp,@AfterOp,@ProjectCode,@EstateName,@PermissionCode,@PermissionLabel,@OpType,@OpTypeName);";
|
||||
|
||||
public static void WriteLog(OperationLog log)
|
||||
{
|
||||
string connString = EnvironmentVariableHelper.IsAspNetCoreProduction ? _proConn : _devConn;
|
||||
|
||||
using (var conn = new MySqlConnection(connString))
|
||||
{
|
||||
conn.Execute(_insertSql, log);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user