提交 1f1a4dfb 编写于 作者: 麦壳饼's avatar 麦壳饼

1. 将时序数据库进行剥离

2. 将数据库访问移动到子目录中
3.将扩展进行分类,尽可能通用。 减少干涉。
上级 5d8a0151
using CoAP;
using DotNetCore.CAP.Dashboard.NodeDiscovery;
using EFCore.Sharding;

using IoTSharp.Data;
using IoTSharp.X509Extensions;
using MaiKeBing.HostedService.ZeroMQ;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
......@@ -72,32 +68,24 @@ namespace IoTSharp
/// </summary>
public MqttClientSetting MqttClient { get; set; } = new MqttClientSetting() { MqttBroker = "built-in", UserName = Guid.NewGuid().ToString(), Password = Guid.NewGuid().ToString(), Port = 1883 };
public Dictionary<string, string> ConnectionStrings { get; set; }
public CoapConfig CoapServer { get; set; } = new CoapConfig();
public ModBusServerSetting ModBusServer { get; set; } = new ModBusServerSetting();
public TelemetryStorage TelemetryStorage { get; set; } = TelemetryStorage.SingleTable;
public ShardingSetting Sharding { get; set; } = new ShardingSetting();
public EventBusStore EventBusStore { get; set; } = EventBusStore.InMemory;
public EventBusMQ EventBusMQ { get; set; } = EventBusMQ.InMemory;
public int ConsumerThreadCount { get; set; } = Environment.ProcessorCount;
public int DbContextPoolSize { get; set; } = 128;
public CachingUseIn CachingUseIn { get; set; } = CachingUseIn.InMemory;
public string CachingUseRedisHosts { get; set; }
public DiscoveryOptions Discovery { get; set; } = null;
public ZMQOption ZMQOption { get; set; } = null;
//public DiscoveryOptions Discovery { get; set; } = null;
//public ZMQOption ZMQOption { get; set; } = null;
public int SucceedMessageExpiredAfter { get; set; } = 3600 * 6;
public DataBaseType DataBase { get; set; } = DataBaseType.PostgreSql;
public int RuleCachingExpiration { get; set; } = 60;
public string SilkierUsername { get; set; }
public string SilkierPassword { get; set; }
}
public class ShardingSetting
{
public DatabaseType DatabaseType { get; set; } = DatabaseType.PostgreSql;
public ExpandByDateMode ExpandByDateMode { get; set; } = ExpandByDateMode.PerMonth;
}
public class ModBusServerSetting
{
......
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>
namespace IoTSharp.Contracts
{
public class TelemetryDataDto
{
public string KeyName { get; set; }
public DateTime DateTime { get; set; }
public Data.DataType DataType { get; set; }
public object Value { get; set; }
}
}
\ No newline at end of file
using IoTSharp.Data;
using IoTSharp.Dtos;
using IoTSharp.Extensions;
using IoTSharp.Contracts;
using IoTSharp.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Dic = System.Collections.Generic.Dictionary<string, System.Exception>;
using Microsoft.EntityFrameworkCore.Infrastructure;
namespace IoTSharp.Storage
{
......
using IoTSharp.Data;
using IoTSharp.Dtos;
using Microsoft.AspNetCore.Mvc;
using IoTSharp.Contracts;
using IoTSharp.Data;
using System;
using System.Collections.Generic;
using System.Linq;
......
using hyjiacan.py4n;
using InfluxDB.Client;
using InfluxDB.Client;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Core.Flux.Domain;
using InfluxDB.Client.Writes;
using IoTSharp.Contracts;
using IoTSharp.Data;
using IoTSharp.Dtos;
using IoTSharp.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.ObjectPool;
using Microsoft.Extensions.Options;
using Org.BouncyCastle.Utilities.Encoders;
using Silkier;
using Silkier.EFCore;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
......
using Apache.IoTDB.Data;
using Apache.IoTDB.DataStructure;
using IoTSharp.Contracts;
using IoTSharp.Data;
using IoTSharp.Dtos;
using IoTSharp.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Silkier;
using Silkier.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
......
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Apache.IoTDB.Data" Version="0.13.0.8" />
<PackageReference Include="EFCore.Sharding" Version="6.0.7" />
<PackageReference Include="hyjiacan.pinyin4net" Version="4.1.1" />
<PackageReference Include="InfluxDB.Client" Version="4.5.0" />
<PackageReference Include="IoTSharp.Data.Taos" Version="2.6.2" />
<PackageReference Include="PinusDB" Version="1.0.10" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IoTSharp.Contracts\IoTSharp.Contracts.csproj" />
<ProjectReference Include="..\IoTSharp.Data\IoTSharp.Data.csproj" />
<ProjectReference Include="..\IoTSharp.Extensions.EFCore\IoTSharp.Extensions.EFCore.csproj" />
<ProjectReference Include="..\IoTSharp.Extensions\IoTSharp.Extensions.csproj" />
</ItemGroup>
</Project>
using hyjiacan.py4n;
using IoTSharp.Contracts;
using IoTSharp.Data;
using IoTSharp.Dtos;
using IoTSharp.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.ObjectPool;
using Microsoft.Extensions.Options;
using Org.BouncyCastle.Utilities.Encoders;
using PinusDB.Data;
using Silkier.EFCore;
using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IoTSharp.Storage
{
......
using EFCore.Sharding;
using IoTSharp.Contracts;
using IoTSharp.Data;
using IoTSharp.Dtos;
using IoTSharp.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
......
using hyjiacan.py4n;
using IoTSharp.Data;
using IoTSharp.Dtos;
using IoTSharp.Extensions;
using IoTSharp.Data;
using IoTSharp.Data.Taos;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.ObjectPool;
using Microsoft.Extensions.Options;
using Org.BouncyCastle.Utilities.Encoders;
using Silkier;
using Silkier.EFCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using IoTSharp.Contracts;
using IoTSharp.Extensions;
using hyjiacan.py4n;
namespace IoTSharp.Storage
{
......
using IoTSharp.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Silkier.EFCore;
using System.Collections.Generic;
using System.Threading.Tasks;
......
using IoTSharp.Data;
using IoTSharp.Dtos;
using Microsoft.AspNetCore.Routing.Matching;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using IoTSharp.Contracts;
using IoTSharp.Data;
using Microsoft.EntityFrameworkCore;
using MQTTnet;
using Newtonsoft.Json.Linq;
using Org.BouncyCastle.Crypto.Modes.Gcm;
using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Dic = System.Collections.Generic.Dictionary<string, System.Exception>;
namespace IoTSharp.Extensions
namespace IoTSharp.Data
{
public static class DataExtension
{
internal static (bool ok, Device device) GetDeviceByTokenWithTenantCustomer(this ApplicationDbContext _context, string access_token)
public static (bool ok, Device device) GetDeviceByTokenWithTenantCustomer(this ApplicationDbContext _context, string access_token)
{
var deviceIdentity = from id in _context.DeviceIdentities.Include(di => di.Device) where id.IdentityId == access_token && id.IdentityType == IdentityType.AccessToken select id;
var devices = from dev in _context.Device.Include(g=>g.Customer).Include(g=>g.Tenant) where deviceIdentity.Any() && dev.Id == deviceIdentity.FirstOrDefault().Device.Id select dev;
bool ok = deviceIdentity == null || !devices.Any();
return (ok, devices.FirstOrDefault());
}
internal static (bool ok, Device device) GetDeviceByToken(this ApplicationDbContext _context, string access_token)
public static (bool ok, Device device) GetDeviceByToken(this ApplicationDbContext _context, string access_token)
{
var deviceIdentity = from id in _context.DeviceIdentities.Include(di => di.Device) where id.IdentityId == access_token && id.IdentityType == IdentityType.AccessToken select id;
var devices = from dev in _context.Device where deviceIdentity.Any() && dev.Id == deviceIdentity.FirstOrDefault().Device.Id select dev;
......@@ -40,7 +36,7 @@ namespace IoTSharp.Extensions
/// <param name="deviceId"></param>
/// <param name="_context"></param>
/// <returns></returns>
internal static async Task<(int ret, Dic exceptions)> SaveAsync<L>(this ApplicationDbContext _context, Dictionary<string, object> data, Guid deviceId, DataSide dataSide) where L : DataStorage, new()
public static async Task<(int ret, Dic exceptions)> SaveAsync<L>(this ApplicationDbContext _context, Dictionary<string, object> data, Guid deviceId, DataSide dataSide) where L : DataStorage, new()
{
Dic exceptions = _context.PreparingData<L>(data, deviceId, dataSide);
int ret = await _context.SaveChangesAsync();
......@@ -55,7 +51,7 @@ namespace IoTSharp.Extensions
/// <param name="deviceId"></param>
/// <param name="dataSide"></param>
/// <returns></returns>
internal static Dic PreparingData<L>(this ApplicationDbContext _context, Dictionary<string, object> data, Guid deviceId, DataSide dataSide)
public static Dic PreparingData<L>(this ApplicationDbContext _context, Dictionary<string, object> data, Guid deviceId, DataSide dataSide)
where L : DataStorage, new()
{
......@@ -176,7 +172,7 @@ namespace IoTSharp.Extensions
}
return obj;
}
internal static void FillKVToMe<T>(this T tdata, KeyValuePair<string, object> kp) where T : IDataStorage
public static void FillKVToMe<T>(this T tdata, KeyValuePair<string, object> kp) where T : IDataStorage
{
var tc = Type.GetTypeCode(kp.Value.GetType());
......@@ -271,10 +267,7 @@ namespace IoTSharp.Extensions
break;
}
}
public static Dictionary<string, object> ConvertPayloadToDictionary(this MqttApplicationMessage msg)
{
return JToken.Parse(msg.ConvertPayloadToString()??"{}")?.JsonToDictionary();
}
public static Dictionary<string, object> JsonToDictionary(this JToken jojb)
{
......
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
namespace IoTSharp.Data
{
//Org.BouncyCastle.Utilities.Encoders
public sealed class Hex
{
private static readonly HexEncoder encoder = new HexEncoder();
private Hex()
{
}
public static string ToHexString(
byte[] data)
{
return ToHexString(data, 0, data.Length);
}
public static string ToHexString(
byte[] data,
int off,
int length)
{
byte[] hex = Encode(data, off, length);
return Encoding.ASCII.GetString(hex, 0, hex.Length);
}
/**
* encode the input data producing a Hex encoded byte array.
*
* @return a byte array containing the Hex encoded data.
*/
public static byte[] Encode(
byte[] data,
int off,
int length)
{
MemoryStream bOut = new MemoryStream(length * 2);
encoder.Encode(data, off, length, bOut);
return bOut.ToArray();
}
/**
* Hex encode the byte data writing it to the given output stream.
*
* @return the number of bytes produced.
*/
public static int Encode(
byte[] data,
int off,
int length,
Stream outStream)
{
return encoder.Encode(data, off, length, outStream);
}
/**
* decode the Hex encoded input data. It is assumed the input data is valid.
*
* @return a byte array representing the decoded data.
*/
public static byte[] Decode(
byte[] data)
{
MemoryStream bOut = new MemoryStream((data.Length + 1) / 2);
encoder.Decode(data, 0, data.Length, bOut);
return bOut.ToArray();
}
/**
* decode the Hex encoded string data - whitespace will be ignored.
*
* @return a byte array representing the decoded data.
*/
public static byte[] Decode(
string data)
{
MemoryStream bOut = new MemoryStream((data.Length + 1) / 2);
encoder.DecodeString(data, bOut);
return bOut.ToArray();
}
/**
* decode the Hex encoded string data writing it to the given output stream,
* whitespace characters will be ignored.
*
* @return the number of bytes produced.
*/
public static int Decode(
string data,
Stream outStream)
{
return encoder.DecodeString(data, outStream);
}
}
public class HexEncoder
{
protected readonly byte[] encodingTable =
{
(byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
(byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
};
/*
* set up the decoding table.
*/
protected readonly byte[] decodingTable = new byte[128];
protected void InitialiseDecodingTable()
{
Fill(decodingTable, (byte)0xff);
for (int i = 0; i < encodingTable.Length; i++)
{
decodingTable[encodingTable[i]] = (byte)i;
}
decodingTable['A'] = decodingTable['a'];
decodingTable['B'] = decodingTable['b'];
decodingTable['C'] = decodingTable['c'];
decodingTable['D'] = decodingTable['d'];
decodingTable['E'] = decodingTable['e'];
decodingTable['F'] = decodingTable['f'];
}
public HexEncoder()
{
InitialiseDecodingTable();
}
public int Encode(byte[] inBuf, int inOff, int inLen, byte[] outBuf, int outOff)
{
int inPos = inOff;
int inEnd = inOff + inLen;
int outPos = outOff;
while (inPos < inEnd)
{
uint b = inBuf[inPos++];
outBuf[outPos++] = encodingTable[b >> 4];
outBuf[outPos++] = encodingTable[b & 0xF];
}
return outPos - outOff;
}
/**
* encode the input data producing a Hex output stream.
*
* @return the number of bytes produced.
*/
public int Encode(byte[] buf, int off, int len, Stream outStream)
{
if (len < 0)
return 0;
byte[] tmp = new byte[72];
int remaining = len;
while (remaining > 0)
{
int inLen = System.Math.Min(36, remaining);
int outLen = Encode(buf, off, inLen, tmp, 0);
outStream.Write(tmp, 0, outLen);
off += inLen;
remaining -= inLen;
}
return len * 2;
}
private static bool Ignore(char c)
{
return c == '\n' || c == '\r' || c == '\t' || c == ' ';
}
/**
* decode the Hex encoded byte data writing it to the given output stream,
* whitespace characters will be ignored.
*
* @return the number of bytes produced.
*/
public int Decode(
byte[] data,
int off,
int length,
Stream outStream)
{
byte b1, b2;
int outLen = 0;
byte[] buf = new byte[36];
int bufOff = 0;
int end = off + length;
while (end > off)
{
if (!Ignore((char)data[end - 1]))
break;
end--;
}
int i = off;
while (i < end)
{
while (i < end && Ignore((char)data[i]))
{
i++;
}
b1 = decodingTable[data[i++]];
while (i < end && Ignore((char)data[i]))
{
i++;
}
b2 = decodingTable[data[i++]];
if ((b1 | b2) >= 0x80)
throw new IOException("invalid characters encountered in Hex data");
buf[bufOff++] = (byte)((b1 << 4) | b2);
if (bufOff == buf.Length)
{
outStream.Write(buf, 0, bufOff);
bufOff = 0;
}
outLen++;
}
if (bufOff > 0)
{
outStream.Write(buf, 0, bufOff);
}
return outLen;
}
/**
* decode the Hex encoded string data writing it to the given output stream,
* whitespace characters will be ignored.
*
* @return the number of bytes produced.
*/
public int DecodeString(
string data,
Stream outStream)
{
byte b1, b2;
int length = 0;
byte[] buf = new byte[36];
int bufOff = 0;
int end = data.Length;
while (end > 0)
{
if (!Ignore(data[end - 1]))
break;
end--;
}
int i = 0;
while (i < end)
{
while (i < end && Ignore(data[i]))
{
i++;
}
b1 = decodingTable[data[i++]];
while (i < end && Ignore(data[i]))
{
i++;
}
b2 = decodingTable[data[i++]];
if ((b1 | b2) >= 0x80)
throw new IOException("invalid characters encountered in Hex data");
buf[bufOff++] = (byte)((b1 << 4) | b2);
if (bufOff == buf.Length)
{
outStream.Write(buf, 0, bufOff);
bufOff = 0;
}
length++;
}
if (bufOff > 0)
{
outStream.Write(buf, 0, bufOff);
}
return length;
}
internal byte[] DecodeStrict(string str, int off, int len)
{
if (null == str)
throw new ArgumentNullException("str");
if (off < 0 || len < 0 || off > (str.Length - len))
throw new IndexOutOfRangeException("invalid offset and/or length specified");
if (0 != (len & 1))
throw new ArgumentException("a hexadecimal encoding must have an even number of characters", "len");
int resultLen = len >> 1;
byte[] result = new byte[resultLen];
int strPos = off;
for (int i = 0; i < resultLen; ++i)
{
byte b1 = decodingTable[str[strPos++]];
byte b2 = decodingTable[str[strPos++]];
if ((b1 | b2) >= 0x80)
throw new IOException("invalid characters encountered in Hex data");
result[i] = (byte)((b1 << 4) | b2);
}
return result;
}
public static void Fill(
byte[] buf,
byte b)
{
int i = buf.Length;
while (i > 0)
{
buf[--i] = b;
}
}
public static string FromAsciiByteArray(
byte[] bytes)
{
return Encoding.ASCII.GetString(bytes, 0, bytes.Length);
}
}
}
......@@ -10,9 +10,23 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Analyzers" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.8" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IoTSharp.Contracts\IoTSharp.Contracts.csproj" />
</ItemGroup>
</Project>
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Microsoft.Extensions.DependencyInjection
{
public static class DependencyInjectionExtension
{
public static T GetRequiredService<T>(this IServiceScopeFactory scopeFactor) =>
scopeFactor.CreateScope().ServiceProvider.GetRequiredService<T>();
}
}
\ No newline at end of file
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.Extensions.Hosting
{
public static class HostExtension
{
public static IHostBuilder ConfigureWindowsServices(this IHostBuilder hostBuilder)
{
bool IsWindowsService = false;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
using (var process = GetParent(Process.GetCurrentProcess()))
{
IsWindowsService = process != null && process.ProcessName == "services";
}
}
if (Environment.CommandLine.Contains("--usebasedirectory") || (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && IsWindowsService))
{
hostBuilder.UseContentRoot(AppContext.BaseDirectory);
System.IO.Directory.SetCurrentDirectory(AppContext.BaseDirectory);
hostBuilder.UseWindowsService();
}
return hostBuilder;
}
public static IHostBuilder UseJsonToSettings(this IHostBuilder hostBuilder, string filename)
{
return hostBuilder.ConfigureAppConfiguration(builder =>
{
try
{
if (System.IO.File.Exists(filename))
{
builder.AddJsonFile(filename, true);
}
}
catch (System.Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
});
}
public static IWebHostBuilder UseContentRootAsEnv(this IWebHostBuilder hostBuilder)
{
bool IsWindowsService = false;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
using (var process = GetParent(Process.GetCurrentProcess()))
{
IsWindowsService = process != null && process.ProcessName == "services";
}
}
if (Environment.CommandLine.Contains("--usebasedirectory") || (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && IsWindowsService))
{
hostBuilder.UseContentRoot(AppContext.BaseDirectory);
}
else
{
if (!Debugger.IsAttached)
{
hostBuilder.UseContentRoot(System.IO.Directory.GetCurrentDirectory());
}
}
return hostBuilder;
}
private static Process GetParent(Process child)
{
var parentId = 0;
var handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (handle == IntPtr.Zero)
{
return null;
}
var processInfo = new PROCESSENTRY32
{
dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32))
};
if (!Process32First(handle, ref processInfo))
{
return null;
}
do
{
if (child.Id == processInfo.th32ProcessID)
{
parentId = (int)processInfo.th32ParentProcessID;
}
} while (parentId == 0 && Process32Next(handle, ref processInfo));
if (parentId > 0)
{
return Process.GetProcessById(parentId);
}
return null;
}
private static uint TH32CS_SNAPPROCESS = 2;
[DllImport("kernel32.dll")]
internal static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID);
[DllImport("kernel32.dll")]
internal static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
[StructLayout(LayoutKind.Sequential)]
public struct PROCESSENTRY32
{
public uint dwSize;
public uint cntUsage;
public uint th32ProcessID;
public IntPtr th32DefaultHeapID;
public uint th32ModuleID;
public uint cntThreads;
public uint th32ParentProcessID;
public int pcPriClassBase;
public uint dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szExeFile;
}
}
}
using System.Security.Cryptography;
using System.Text;
namespace Microsoft.AspNetCore.Identity
{
public static class IdentityExtension
{
/// Hashes an email with MD5. Suitable for use with Gravatar profile
/// image urls
public static string Gravatar(this IdentityUser user)
{
string email = user.Email;
// Create a new instance of the MD5CryptoServiceProvider object.
MD5 md5Hasher = MD5.Create();
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(email));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
return string.Format("http://www.gravatar.com/avatar/{0}", sBuilder.ToString()); ; // Return the hexadecimal string.
}
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>1.0.1</Version>
<Product>IoTSharp.Extensions.AspNetCore</Product>
<Authors>MaikeBing</Authors>
<PackageIconUrl />
<RepositoryUrl>https://github.com/IoTSharp/IoTSharp</RepositoryUrl>
<PackageProjectUrl>https://github.com/IoTSharp/IoTSharp</PackageProjectUrl>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
</ItemGroup>
</Project>
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Mvc
{
public static class MVCExtensions
{
public static BadRequestObjectResult ExceptionRequest(this ControllerBase @base, Exception exception)
{
MethodBase mb = new StackTrace(exception).GetFrame(0).GetMethod();
MethodBase cu = new StackTrace(true).GetFrame(0).GetMethod();
return @base.BadRequest(new
{
exception.Message,
exception.StackTrace,
ExceptionMethod = mb.DeclaringType.FullName + "." + mb.Name,
MethodName = cu.Name
});
}
public static BadRequestObjectResult ExceptionRequest<T>(this ControllerBase @base, T code, string msg, Exception exception)
{
MethodBase mb = new StackTrace(exception).GetFrame(0).GetMethod();
MethodBase cu = new StackTrace(true).GetFrame(0).GetMethod();
return @base.BadRequest(new
{
code,
msg,
data = new
{
ExceptionMethod = mb.DeclaringType.FullName + "." + mb.Name,
MethodName = cu.Name
}
});
}
public static BadRequestObjectResult ExceptionRequest(this ControllerBase @base, int code, string msg, Exception exception)
=> ExceptionRequest<int>(@base, code, msg, exception);
}
}
using Microsoft.Extensions.DependencyInjection;
using System;
namespace Microsoft.Extensions.ObjectPool
{
internal class PooledObjectByFuncPolicy<T> : PooledObjectPolicy<T> where T : class
{
private readonly Func<T> _createfunc;
private readonly Func<T, bool> _returnfunc;
public PooledObjectByFuncPolicy(Func<T> createfunc)
{
_createfunc = createfunc;
_returnfunc = t => true;
}
public PooledObjectByFuncPolicy(Func<T> createfunc, Func<T, bool> returnfunc)
{
_createfunc = createfunc;
_returnfunc = returnfunc;
}
public override T Create()
{
return _createfunc.Invoke();
}
public override bool Return(T obj)
{
return _returnfunc.Invoke(obj);
}
}
public static class ObjectPoolExtension
{
/// <summary>
/// 添加类型为<typeparamref name="T"/>至对象池进行复用
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddObjectPool<T>(this IServiceCollection services) where T : class,new ()
{
return services.AddSingleton(s =>
{
var provider = s.GetRequiredService<ObjectPoolProvider>();
return provider.Create<T>();
});
}
/// <summary>
/// 将<typeparamref name="T"/>类型添加至对象池, 并使用<paramref name="_create"/>进行创建初始化, 使用<paramref name="_returnfunc"/>归还
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="services"></param>
/// <param name="_create"></param>
/// <param name="_returnfunc"></param>
/// <returns></returns>
public static IServiceCollection AddObjectPool<T>(this IServiceCollection services, Func<T> _create, Func<T, bool> _returnfunc) where T : class
{
return services.AddSingleton(s =>
{
var provider = s.GetRequiredService<ObjectPoolProvider>();
return provider.Create(new PooledObjectByFuncPolicy<T>(_create, _returnfunc));
});
}
/// <summary>
/// 将<typeparamref name="T"/>类型添加至对象池, 并使用<paramref name="_create"/>进行创建初始化
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="services"></param>
/// <param name="_create"></param>
/// <returns></returns>
public static IServiceCollection AddObjectPool<T>(this IServiceCollection services, Func<T> _create) where T : class
{
return services.AddObjectPool(_create, t => true);
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>1.0.1</Version>
<Authors>MaikeBing</Authors>
<PackageIconUrl />
<PackageProjectUrl>https://github.com/IoTSharp/IoTSharp</PackageProjectUrl>
<RepositoryUrl>https://github.com/IoTSharp/IoTSharp</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
</ItemGroup>
</Project>
此差异已折叠。

namespace System.Collections.Generic
{
public static class CollectionsExtension
{
public static IEnumerable<TSource> Distinct<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
HashSet<TKey> seenKeys = new HashSet<TKey>();
foreach (TSource element in source)
{
if (seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
}
}
\ No newline at end of file
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace System.Data
{
public static class DataExtension
{
public static IList<T> ToIList<T>(this DataTable dt) where T : class => dt.ToList<T>();
public static List<T> ToList<T>(this DataTable dt) where T : class
{
List<T> jArray = new List<T>();
var prs = typeof(T).GetProperties();
try
{
for (int il = 0; il < dt.Rows.Count; il++)
{
T jObject = Activator.CreateInstance<T>();
for (int i = 0; i < dt.Columns.Count; i++)
{
try
{
string strKey = dt.Columns[i].ColumnName;
if (dt.Rows[il].ItemArray[i] != DBNull.Value)
{
object obj = Convert.ChangeType(dt.Rows[il].ItemArray[i], dt.Columns[i].DataType);
var p = prs.FirstOrDefault(px => px.Name.ToLower() == strKey.ToLower());
if (p != null)
{
SetValue(jObject, dt.Columns[i].DataType, obj, p);
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
jArray.Add(jObject);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
return jArray;
}
/// <summary>
/// DataTable 转为 Json
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public static JArray ToJson(this DataTable dt)
{
JArray jArray = new JArray();
try
{
for (int il = 0; il < dt.Rows.Count; il++)
{
JObject jObject = new JObject();
for (int i = 0; i < dt.Columns.Count; i++)
{
try
{
string strKey = dt.Columns[i].ColumnName;
if (dt.Rows[il].ItemArray[i] != DBNull.Value)
{
object obj = Convert.ChangeType(dt.Rows[il].ItemArray[i], dt.Columns[i].DataType);
jObject.Add(strKey, JToken.FromObject(obj));
}
}
catch (Exception)
{
}
}
jArray.Add(jObject);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
return jArray;
}
private static void SetValue<T>(T jObject, Type ft, object obj, System.Reflection.FieldInfo p)
{
if (p.FieldType == ft)
{
p.SetValue(jObject, obj);
}
else if (p.FieldType == typeof(DateTime) && ft == typeof(string))
{
if (DateTime.TryParse((string)obj, out DateTime dt))
{
p.SetValue(jObject, dt);
}
}
else
{
p.SetValue(jObject, Convert.ChangeType(obj, p.FieldType));
}
}
private static void SetValue<T>(T jObject, Type ft, object obj, System.Reflection.PropertyInfo p) where T : class
{
if (p.PropertyType == ft)
{
p.SetValue(jObject, obj);
}
else if (p.PropertyType == typeof(DateTime) && ft == typeof(string))
{
if (DateTime.TryParse((string)obj, out DateTime dt))
{
p.SetValue(jObject, dt);
}
}
else
{
p.SetValue(jObject, Convert.ChangeType(obj, p.PropertyType));
}
}
/// <summary>
///将DataTable转换为标准的CSV字符串
/// </summary>
/// <param name="dt">数据表</param>
/// <returns>返回标准的CSV</returns>
/// <seealso cref="https://github.com/Coldairarrow/EFCore.Sharding/blob/5216ffc6330e84de484865eae645c0be1f2be180/src/EFCore.Sharding.Tests/Util/Extention.DataTable.cs"/>
public static string ToCsvStr(this DataTable dt)
{
//以半角逗号(即,)作分隔符,列为空也要表达其存在。
//列内容如存在半角逗号(即,)则用半角引号(即"")将该字段值包含起来。
//列内容如存在半角引号(即")则应替换成半角双引号("")转义,并用半角引号(即"")将该字段值包含起来。
StringBuilder sb = new StringBuilder();
DataColumn colum;
foreach (DataRow row in dt.Rows)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
colum = dt.Columns[i];
if (i != 0) sb.Append(",");
if (colum.DataType == typeof(string) && row[colum].ToString().Contains(","))
{
sb.Append("\"" + row[colum].ToString().Replace("\"", "\"\"") + "\"");
}
else sb.Append(row[colum].ToString());
}
sb.AppendLine();
}
return sb.ToString();
}
}
}
\ No newline at end of file
using IoTSharp.Extensions;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace System.Data
{
public static class DbReaderExtensions
{
public static JArray ToJson(this IDataReader dataReader)
{
JArray jArray = new JArray();
try
{
while (dataReader.Read())
{
JObject jObject = new JObject();
for (int i = 0; i < dataReader.FieldCount; i++)
{
try
{
string strKey = dataReader.GetName(i);
if (dataReader[i] != DBNull.Value)
{
object obj = Convert.ChangeType(dataReader[i], dataReader.GetFieldType(i));
jObject.Add(strKey, JToken.FromObject(obj));
}
}
catch (Exception)
{
}
}
jArray.Add(jObject);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
finally
{
dataReader.Close();
}
return jArray;
}
public static IDbCommand CreateCommand(this IDbConnection db, string commandText)
{
var cmd = db.CreateCommand();
cmd.CommandText = commandText;
return cmd;
}
public static IDbCommand SetCommandTimeout(this IDbCommand command, TimeSpan span)
{
command.CommandTimeout = (int)span.TotalSeconds;
return command;
}
public static IDictionary<string, DbColumn> GetSchema<T>(this IDataReader dr) => GetSchema<T>((DbDataReader)dr);
public static IDictionary<string, DbColumn> GetSchema<T>(this DbDataReader dr)
{
IDictionary<string, DbColumn> valuePairs;
if (typeof(T).IsTupleType())
{
var props = typeof(T).GetRuntimeFields();
valuePairs = dr.GetColumnSchema()
.ToDictionary(key => key.ColumnName.ToLower());
}
else
{
var props = typeof(T).GetRuntimeProperties();
valuePairs = dr.GetColumnSchema()
.Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower()))
.ToDictionary(key => key.ColumnName.ToLower());
}
return valuePairs;
}
public static T MapObject<T>(this IDataReader dr, IDictionary<string, DbColumn> colMapping) => MapObject<T>((DbDataReader)dr, colMapping);
public static T MapObject<T>(this DbDataReader dr, IDictionary<string, DbColumn> colMapping)
{
T t;
if (typeof(T).IsSqlSimpleType())
{
t = (T)dr.GetValue(0);
}
else
{
T obj = Activator.CreateInstance<T>();
if (typeof(T).IsTupleType())
{
var fields = typeof(T).GetRuntimeFields().ToArray();
//https://stackoverflow.com/questions/59000557/valuetuple-set-fields-via-reflection
object xobj = obj;
for (int i = 0; i < fields.Length; i++)
{
try
{
if (dr.GetValue(i) == DBNull.Value)
{
fields[i].SetValue(xobj, fields[i].FieldType.GetDefaultValue());
}
else
{
var val = Convert.ChangeType(dr.GetValue(i), fields[i].FieldType);
fields[i].SetValue(xobj, val);
}
}
catch (Exception ex)
{
Debug.WriteLine($"{fields[i].Name} {ex.Message}");
}
}
obj = (T)xobj;
}
else
{
IEnumerable<PropertyInfo> props = typeof(T).GetRuntimeProperties();
foreach (var prop in props)
{
var propName = prop.Name.ToLower();
if (colMapping.ContainsKey(propName))
{
var val = dr.GetValue(colMapping[prop.Name.ToLower()].ColumnOrdinal.Value);
var type = Nullable.GetUnderlyingType(prop.PropertyType);
if (type != null && type.IsEnum)
{
val = val == DBNull.Value ? null : Enum.ToObject(type, val);
}
var evar = System.Convert.ChangeType(val == DBNull.Value ? prop.PropertyType.GetDefaultValue() : val, prop.PropertyType);
prop.SetValue(obj, evar);
}
else
{
prop.SetValue(obj, prop.PropertyType.GetDefaultValue());
}
}
}
t = obj;
}
return t;
}
/// <summary>
/// 获取变量的默认值
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static object GetDefaultValue(this Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
public static async Task<IList<T>> ToIListAsync<T>(this IDataReader dr) => await ToListAsync<T>((DbDataReader)dr);
public static async Task<IList<T>> ToIListAsync<T>(this DbDataReader dr) => await ToListAsync<T>(dr);
public static async Task<List<T>> ToListAsync<T>(this IDataReader dr) => await ToListAsync<T>((DbDataReader)dr);
public static async Task<List<T>> ToListAsync<T>(this DbDataReader dr)
{
var objList = new List<T>();
var colMapping = dr.GetSchema<T>();
if (dr.HasRows)
while (await dr.ReadAsync())
objList.Add(dr.MapObject<T>(colMapping));
dr.Close();
return objList;
}
public static List<T> ToList<T>(this IDataReader dr) => ToList<T>((DbDataReader)dr);
public static IList<T> ToIList<T>(this IDataReader dr) => ToList<T>((DbDataReader)dr);
public static IList<T> ToIList<T>(this DbDataReader dr) => ToList<T>(dr);
public static List<T> ToList<T>(this DbDataReader dr)
{
var objList = new List<T>();
var colMapping = dr.GetSchema<T>();
if (dr.HasRows)
while (dr.Read())
objList.Add(dr.MapObject<T>(colMapping));
dr.Close();
return objList;
}
public static DataTable ToDataTable(this IDataReader dr) => ToDataTable((DbDataReader)dr);
public static string ToCvsstr(this IDataReader dr) => dr.ToDataTable().ToCsvStr();
public static DataTable ToDataTable(this DbDataReader dr)
{
DataTable objDataTable = new DataTable();
for (int intCounter = 0; intCounter < dr.FieldCount; ++intCounter)
{
objDataTable.Columns.Add(dr.GetName(intCounter), dr.GetFieldType(intCounter));
}
if (dr.HasRows)
{
objDataTable.BeginLoadData();
object[] objValues = new object[dr.FieldCount];
while (dr.Read())
{
dr.GetValues(objValues);
objDataTable.LoadDataRow(objValues, true);
}
objDataTable.EndLoadData();
}
dr.Close();
return objDataTable;
}
public static async Task<DataTable> ToDataTableAsync(this IDataReader dr) => await ToDataTableAsync((DbDataReader)dr);
public static async Task<DataTable> ToDataTableAsync(this DbDataReader dr)
{
DataTable objDataTable = new DataTable();
for (int intCounter = 0; intCounter < dr.FieldCount; ++intCounter)
{
objDataTable.Columns.Add(dr.GetName(intCounter), dr.GetFieldType(intCounter));
}
if (dr.HasRows)
{
objDataTable.BeginLoadData();
object[] objValues = new object[dr.FieldCount];
while (await dr.ReadAsync())
{
dr.GetValues(objValues);
objDataTable.LoadDataRow(objValues, true);
}
objDataTable.EndLoadData();
}
dr.Close();
return objDataTable;
}
public static async Task<T> FirstOrDefaultAsync<T>(this IDataReader dr) => await FirstOrDefaultAsync<T>((DbDataReader)dr);
public static async Task<T> FirstOrDefaultAsync<T>(this DbDataReader dr)
{
var colMapping = dr.GetSchema<T>();
if (dr.HasRows)
while (await dr.ReadAsync())
return dr.MapObject<T>(colMapping);
dr.Close();
return default(T);
}
public static T FirstOrDefault<T>(this IDataReader dr) => FirstOrDefault<T>((DbDataReader)dr);
public static T FirstOrDefault<T>(this DbDataReader dr)
{
var colMapping = dr.GetSchema<T>();
if (dr.HasRows)
while (dr.Read())
return dr.MapObject<T>(colMapping);
dr.Close();
return default(T);
}
public static async Task<T> SingleOrDefaultAsync<T>(this IDataReader dr) => await SingleOrDefaultAsync<T>((DbDataReader)dr);
public static async Task<T> SingleOrDefaultAsync<T>(this DbDataReader dr)
{
var colMapping = dr.GetSchema<T>();
T obj = default(T);
bool hasResult = false;
if (dr.HasRows)
while (await dr.ReadAsync())
{
if (hasResult)
throw new InvalidOperationException("Sequence contains more than one matching element");
obj = dr.MapObject<T>(colMapping);
hasResult = true;
}
dr.Close();
return obj;
}
public static T SingleOrDefault<T>(this IDataReader dr) => SingleOrDefault<T>((DbDataReader)dr);
public static T SingleOrDefault<T>(this DbDataReader dr)
{
var colMapping = dr.GetSchema<T>();
T obj = default(T);
bool hasResult = false;
if (dr.HasRows)
while (dr.Read())
{
if (hasResult)
throw new InvalidOperationException("Sequence contains more than one matching element");
obj = dr.MapObject<T>(colMapping);
hasResult = true;
}
dr.Close();
return obj;
}
}
}
\ No newline at end of file
using IoTSharp.Extensions.EFCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Threading.Tasks;
namespace Microsoft.EntityFrameworkCore
{
public static class EFCoreExtension
{
private static IRelationalDatabaseFacadeDependencies GetFacadeDependencies(DatabaseFacade databaseFacade)
{
if (((IDatabaseFacadeDependenciesAccessor)databaseFacade).Dependencies is IRelationalDatabaseFacadeDependencies relationalDatabaseFacadeDependencies)
{
return relationalDatabaseFacadeDependencies;
}
throw new InvalidOperationException(RelationalStrings.RelationalNotInUse);
}
public static int ExecuteNonQuery(this DatabaseFacade databaseFacade, string sql, params object[] parameters)
{
IRelationalDatabaseFacadeDependencies facadeDependencies = GetFacadeDependencies(databaseFacade);
IConcurrencyDetector concurrencyDetector = ((IDatabaseFacadeDependencies)facadeDependencies).ConcurrencyDetector;
using (concurrencyDetector.EnterCriticalSection())
{
var rawSqlCommand = databaseFacade.Build(sql, parameters);
return rawSqlCommand.RelationalCommand.ExecuteNonQuery(new RelationalCommandParameterObject(facadeDependencies.RelationalConnection, rawSqlCommand.ParameterValues, null, ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context, facadeDependencies.CommandLogger));
}
}
public static async Task<int> ExecuteNonQueryAsync(this DatabaseFacade databaseFacade, string sql, params object[] parameters)
{
IRelationalDatabaseFacadeDependencies facadeDependencies = GetFacadeDependencies(databaseFacade);
IConcurrencyDetector concurrencyDetector = ((IDatabaseFacadeDependencies)facadeDependencies).ConcurrencyDetector;
var commandLogger = facadeDependencies.CommandLogger;
using (concurrencyDetector.EnterCriticalSection())
{
var rawSqlCommand = databaseFacade.Build(sql, parameters);
return await rawSqlCommand.RelationalCommand.ExecuteNonQueryAsync(new RelationalCommandParameterObject(facadeDependencies.RelationalConnection, rawSqlCommand.ParameterValues, null, ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context, commandLogger));
}
}
internal static T ExecuteReader<T>(this DatabaseFacade databaseFacade, string sql, object[] parameters, Func<DbDataReader, T> func)
{
T result = default(T);
IRelationalDatabaseFacadeDependencies facadeDependencies = GetFacadeDependencies(databaseFacade);
IConcurrencyDetector concurrencyDetector = ((IDatabaseFacadeDependencies)facadeDependencies).ConcurrencyDetector;
var commandLogger = (facadeDependencies).CommandLogger;
using (concurrencyDetector.EnterCriticalSection())
{
var rawSqlCommand = databaseFacade.Build(sql, parameters);
using (var reader = rawSqlCommand.RelationalCommand.ExecuteReader(new RelationalCommandParameterObject(facadeDependencies.RelationalConnection, rawSqlCommand.ParameterValues, null, ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context, commandLogger)))
{
result = func.Invoke(reader.DbDataReader);
}
}
return result;
}
internal class RAWSQLCommand
{
internal IRelationalCommand RelationalCommand { get; set; }
internal IReadOnlyDictionary<string, object> ParameterValues { get; set; }
}
private static RAWSQLCommand Build(this DatabaseFacade databaseFacade, string sql, params object[] parameters)
{
var builder = GetFacadeDependencies(databaseFacade).RawSqlCommandBuilder;
RAWSQLCommand command;
if (parameters == null || parameters.Length == 0)
{
command = new RAWSQLCommand { RelationalCommand = builder.Build(sql) };
}
else
{
var cmdx = builder.Build(sql, parameters);
command = new RAWSQLCommand() { RelationalCommand = cmdx.RelationalCommand, ParameterValues = cmdx.ParameterValues };
}
return command;
}
public static SqlQuery<T> SqlQuery<T>(this DatabaseFacade databaseFacade, string sql)
{
return new SqlQuery<T>(databaseFacade, sql, Array.Empty<object>());
}
public static SqlQuery<T> SqlQuery<T>(this DatabaseFacade databaseFacade, string sql, params object[] parameters)
{
return new SqlQuery<T>(databaseFacade, sql, parameters);
}
internal static async Task<T> ExecuteReaderAsync<T>(this DatabaseFacade databaseFacade, string sql, object[] parameters, Func<DbDataReader, Task<T>> func)
{
T result = default(T);
IRelationalDatabaseFacadeDependencies facadeDependencies = GetFacadeDependencies(databaseFacade);
IConcurrencyDetector concurrencyDetector = ((IDatabaseFacadeDependencies)facadeDependencies).ConcurrencyDetector;
var commandLogger = facadeDependencies.CommandLogger;
using (concurrencyDetector.EnterCriticalSection())
{
var rawSqlCommand = databaseFacade.Build(sql, parameters);
using (var reader = await rawSqlCommand.RelationalCommand.ExecuteReaderAsync(new RelationalCommandParameterObject(facadeDependencies.RelationalConnection, rawSqlCommand.ParameterValues, null, ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context, commandLogger)))
{
result = await func.Invoke(reader.DbDataReader);
}
}
return result;
}
public static async Task<T> ExecuteScalarAsync<T>(this DatabaseFacade databaseFacade, string sql, params object[] parameters)
=> (T)await ExecuteScalarAsync(databaseFacade, sql, parameters);
public static T ExecuteScalar<T>(this DatabaseFacade databaseFacade, string sql, params object[] parameters)
=> (T)ExecuteScalar(databaseFacade, sql, parameters);
public static async Task<object> ExecuteScalarAsync(this DatabaseFacade databaseFacade, string sql, params object[] parameters)
{
IRelationalDatabaseFacadeDependencies facadeDependencies = GetFacadeDependencies(databaseFacade);
IConcurrencyDetector concurrencyDetector = ((IDatabaseFacadeDependencies)facadeDependencies).ConcurrencyDetector;
var commandLogger = facadeDependencies.CommandLogger;
using (concurrencyDetector.EnterCriticalSection())
{
var rawSqlCommand = databaseFacade.Build(sql, parameters);
return await rawSqlCommand.RelationalCommand.ExecuteScalarAsync(new RelationalCommandParameterObject(facadeDependencies.RelationalConnection, rawSqlCommand.ParameterValues, null, ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context, commandLogger));
}
}
public static object ExecuteScalar(this DatabaseFacade databaseFacade, string sql, params object[] parameters)
{
IRelationalDatabaseFacadeDependencies facadeDependencies = GetFacadeDependencies(databaseFacade);
IConcurrencyDetector concurrencyDetector = ((IDatabaseFacadeDependencies)facadeDependencies).ConcurrencyDetector;
var commandLogger = facadeDependencies.CommandLogger;
using (concurrencyDetector.EnterCriticalSection())
{
var rawSqlCommand = databaseFacade.Build(sql, parameters);
return rawSqlCommand.RelationalCommand.ExecuteScalar(new RelationalCommandParameterObject(facadeDependencies.RelationalConnection, rawSqlCommand.ParameterValues, null, ((IDatabaseFacadeDependenciesAccessor)databaseFacade).Context, commandLogger));
}
}
}
}
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>1.0.1</Version>
<Product>IoTSharp</Product>
<Authors>MaikeBing</Authors>
<RepositoryUrl>https://github.com/IoTSharp/IoTSharp</RepositoryUrl>
<PackageProjectUrl>https://github.com/IoTSharp/IoTSharp</PackageProjectUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.8" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IoTSharp.Extensions\IoTSharp.Extensions.csproj" />
</ItemGroup>
</Project>
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Threading.Tasks;
namespace IoTSharp.Extensions.EFCore
{
public class SqlQuery<T>
{
private DatabaseFacade _databaseFacade;
private string _sql; private object[] _parameters;
public SqlQuery(DatabaseFacade databaseFacade, string sql, object[] parameters)
{
_databaseFacade = databaseFacade;
_sql = sql;
_parameters = parameters;
}
public Task<IList<T>> ToIListAsync()
{
return ExecuteReaderAsync((dbReader) => dbReader.ToIListAsync<T>());
}
public Task<List<T>> ToListAsync()
{
return ExecuteReaderAsync((dbReader) => dbReader.ToListAsync<T>());
}
private Task<U> ExecuteReaderAsync<U>(Func<DbDataReader, Task<U>> p)
{
return _databaseFacade.ExecuteReaderAsync(_sql, _parameters, p);
}
private U ExecuteReader<U>(Func<DbDataReader, U> p)
{
return _databaseFacade.ExecuteReader(_sql, _parameters, p);
}
public async Task<T> FirstOrDefaultAsync()
{
return await ExecuteReaderAsync((dbReader) => dbReader.FirstOrDefaultAsync<T>());
}
public async Task<T> SingleOrDefaultAsync()
{
return await ExecuteReaderAsync((dbReader) => dbReader.SingleOrDefaultAsync<T>());
}
public async Task<T> FirstAsync()
{
var result = await FirstOrDefaultAsync();
if (result == null)
throw new InvalidOperationException("Sequence contains no elements");
return result;
}
public async Task<T> SingleAsync()
{
var result = await SingleOrDefaultAsync();
if (result == null)
throw new InvalidOperationException("Sequence contains no elements");
return result;
}
public IList<T> ToList()
{
return ExecuteReader((dbReader) => dbReader.ToList<T>());
}
public DataTable ToDataTable()
{
return ExecuteReader((dbReader) => dbReader.ToDataTable());
}
public async Task<DataTable> ToDataTableAsync()
{
return await ExecuteReaderAsync((dbReader) => dbReader.ToDataTableAsync());
}
public T FirstOrDefault()
{
return ExecuteReader((dbReader) => dbReader.FirstOrDefault<T>());
}
public T SingleOrDefault()
{
return ExecuteReader((dbReader) => dbReader.SingleOrDefault<T>());
}
public T First()
{
var result = FirstOrDefault();
if (result == null)
throw new InvalidOperationException("Sequence contains no elements");
return result;
}
public T Single()
{
var result = SingleOrDefault();
if (result == null)
throw new InvalidOperationException("Sequence contains no elements");
return result;
}
}
}
\ No newline at end of file
## What is IoTSharp.Extensions.EFCore?
[![Nuget Version](https://img.shields.io/nuget/v/IoTSharp.Extensions.EFCore.svg)](https://www.nuget.org/packages/IoTSharp.Extensions.EFCore/)
IoTSharp.Extensions.EFCore is an extension for EF.Core, and the main features include executing the original sql statement, converting the original sql statement to a tuple or a class or array or json object or DataTable .
IoTSharp.Extensions.EFCore 是一个针对EF.Core的扩展, 主要功能包括 执行原始sql语句, 将原始sql语句转换为 元组或者类或者数组。
## 示例:
```c#
_context.Database.SqlQuery<ImgInfo>("select * from ImageInfo litmt 1 ").FirstOrDefault();
_context.Database.SqlQuery<(int id,string body)>("select id,body from imageInfo").ToListAsync();
_context.Database.ExecuteScalar<long>($"select count(0) from pg_class where relname = '{ImageInfo}'");
var r = _context.Database.ExecuteNonQuery(Properties.Resources._imageinfo);
_context.Database.ExecuteScalar<long>("select count(0) from pg_class where relname = {0}","asdfds");
```
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>1.0.1</Version>
<Authors>MaikeBing</Authors>
<PackageIconUrl />
<PackageProjectUrl>https://github.com/IoTSharp/IoTSharp</PackageProjectUrl>
<RepositoryUrl>https://github.com/IoTSharp/IoTSharp</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="RestSharp" Version="108.0.1" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace RestSharp
{
public static class RestClientExtensions
{
/// <summary>
/// 将<paramref name="body"/>作为 body发起针对<paramref name="resource"/>的请求
/// </summary>
/// <typeparam name="T">返回值</typeparam>
/// <typeparam name="I">body的类型</typeparam>
/// <param name="client"></param>
/// <param name="resource"></param>
/// <param name="body"></param>
/// <returns></returns>
public static T ReqResp<T, I>(this RestClient client, string resource, I body) where I : class
{
return ReqResp<T, I>(client, resource, body, Method.Post, DataFormat.Json, null, null);
}
public static T ReqResp<T, I>(this RestClient client, string resource, I body, Method method = Method.Get, DataFormat dataFormat = DataFormat.Json
, Action<int, string> __log = null
, List<Cookie> cookies = null) where I : class
{
return ReqResp<T>(client, resource, method, __log, cookies, req =>
{
switch (dataFormat)
{
case DataFormat.Json:
req.AddJsonBody(body);
break;
case DataFormat.Xml:
req.AddXmlBody(body);
break;
case DataFormat.None:
break;
default:
break;
}
return req;
});
}
public static T ReqResp<T>(this RestClient client, string resource, Method method = Method.Get
, Action<int, string> __log = null
, List<Cookie> cookies = null
, Func<RestRequest, RestRequest> func = null)
{
var req = new RestRequest(resource, method);
if (func != null)
{
req = func.Invoke(req);
}
return client.ReqResp<T>(req,DataFormat.Json, __log, cookies);
}
public static T ReqResp<T>(this RestClient client, string resource)
=> client.ReqResp<T>(new RestRequest(resource, Method.Get), DataFormat.Json, null, null);
public static T ReqResp<T>(this RestClient client, string resource, Method method = Method.Get, DataFormat dataFormat = DataFormat.Json)
=> client.ReqResp<T>(new RestRequest(resource, method), dataFormat, null, null);
public static T ReqResp<T>(this RestClient client, string resource, Method method = Method.Get, DataFormat dataFormat = DataFormat.Json, Action<int, string> __log = null, List<Cookie> cookies = null)
=> client.ReqResp<T>(new RestRequest(resource, method),dataFormat, __log, cookies);
public static T ReqResp<T>(this RestClient client, Uri resource, Method method = Method.Get, DataFormat dataFormat = DataFormat.Json, Action<int, string> __log = null, List<Cookie> cookies = null)
=> client.ReqResp<T>(new RestRequest(resource, method), dataFormat, __log, cookies);
public static T ReqResp<T>(this RestClient client, Uri resource, Method method = Method.Get, DataFormat dataFormat = DataFormat.Json, Func<RestRequest, RestRequest> func = null)
=> client.ReqResp<T>(new RestRequest(resource, method),dataFormat , null, null, func);
public static T ReqResp<T>(this RestClient client, Uri resource, Method method = Method.Get, DataFormat dataFormat = DataFormat.Json, Action<int, string> __log = null, List<Cookie> cookies = null, Func<RestRequest, RestRequest> func = null)
=> client.ReqResp<T>(new RestRequest(resource,method),dataFormat, __log, cookies, func);
public static T ReqResp<T>(this RestClient client, RestRequest rest, DataFormat dataFormat = DataFormat.Json, Action<int, string> __log = null, List<Cookie> cookies = null, Func<RestRequest, RestRequest> func = null)
{
T result = default;
try
{
if (cookies != null && cookies.Count > 0)
{
cookies.ForEach(co =>
{
client.AddCookie(co.Name, co.Value,co.Port,co.Domain);
});
}
var response = client.Execute(func.Invoke(rest));
if (response.StatusCode == HttpStatusCode.OK && !string.IsNullOrEmpty(response.Content)
&& JToken.Parse(response.Content).ToObject<T>() is T jDResult)
{
result = jDResult;
if (cookies != null)
{
cookies.Clear();
cookies.AddRange(response.Cookies.ToArray());
}
}
else
{
__log?.Invoke((int)response.StatusCode, response.Content);
}
}
catch (Exception ex)
{
__log?.Invoke(-999, ex.Message);
}
return result;
}
}
}
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Reflection;
using IoTSharp.Extensions;
namespace IoTSharp.Extensions
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false, AllowMultiple = true)]
public sealed class BitSectionAttribute : Attribute
{
// See the attribute guidelines at
// http://go.microsoft.com/fwlink/?LinkId=85236
readonly short _len;
// This is a positional argument
public BitSectionAttribute(short len)
{
_len = len;
}
public short Len
{
get { return _len; }
}
public int Index { get; set; }
internal BitVector32.Section Section { get; set; }
}
public static class BitVector32Extensions
{
public static T To<T>(this BitVector32 vector32) where T : class, new()
{
T warn = new();
List<(PropertyInfo pi, BitSectionAttribute bsa)> pairs = new List<(PropertyInfo pi, BitSectionAttribute bsa)>();
warn?.GetType().GetProperties().ToList().ForEach(p =>
{
var bs = p.GetCustomAttributes(typeof(BitSectionAttribute), true).ToList().FirstOrDefault() as BitSectionAttribute;
if (bs != null)
{
pairs.Add((p, bs));
}
});
var lst = pairs.OrderBy(k => k.bsa.Index).ToList();
for (int i = 0; i < lst.Count; i++)
{
var bsa = lst[i].bsa;
var pi = lst[i].pi;
if (i == 0)
{
bsa.Section = BitVector32.CreateSection(bsa.Len);
}
else
{
bsa.Section = BitVector32.CreateSection(bsa.Len, lst[i - 1].bsa.Section);
}
pi.SetValue(warn, vector32[bsa.Section]);
}
return warn;
}
}
}
using System;
using System.Runtime.InteropServices;
namespace IoTSharp.Extensions
{
public static class EndianExtensions
{
public static byte[] ToBytes(this short v) => BitConverter.GetBytes(v);
public static short ToShort(this byte[] v) => BitConverter.ToInt16(v, 0);
public static ushort ToUShort(this byte[] v) => BitConverter.ToUInt16(v, 0);
public static byte[] ToBytes(this ushort v) => BitConverter.GetBytes(v);
public static byte[] ToBytes(this int v) => BitConverter.GetBytes(v);
public static int ToInt(this byte[] v) => BitConverter.ToInt32(v, 0);
public static byte[] ToBytes(this uint v) => BitConverter.GetBytes(v);
public static uint ToUInt(this byte[] v) => BitConverter.ToUInt32(v, 0);
public static byte[] ToBytes(this long v) => BitConverter.GetBytes(v);
public static ulong ToULong(this byte[] v) => BitConverter.ToUInt64(v, 0);
public static byte[] ToBytes(this ulong v) => BitConverter.GetBytes(v);
public static long ToLong(this byte[] v) => BitConverter.ToInt64(v, 0);
public static int ToInt(this short v) => v;
public static ushort ToUShort(this short v) => (ushort)v;
public static uint ToUInt(this short v) => (uint)v;
public static long ToLong(this short v) => v;
public static ulong ToULong(this short v) => (ulong)v;
public static int ToInt(this ushort v) => v;
public static short ToShort(this short v) => v;
public static uint ToUInt(this ushort v) => v;
public static long ToLong(this ushort v) => v;
public static ulong ToULong(this ushort v) => v;
public static ushort ToUShort(this int v) => (ushort)v;
public static short ToShort(this int v) => (short)v;
public static uint ToUInt(this int v) => (uint)v;
public static long ToLong(this int v) => v;
public static ulong ToULong(this int v) => (ulong)v;
public static ushort ToUShort(this uint v) => (ushort)v;
public static short ToShort(this uint v) => (short)v;
public static int ToInt(this uint v) => (int)v;
public static long ToLong(this uint v) => v;
public static ulong ToULong(this uint v) => v;
public static ushort ToUShort(this long v) => (ushort)v;
public static short ToShort(this long v) => (short)v;
public static int ToInt(this long v) => (int)v;
public static uint ToUInt(this long v) => (uint)v;
public static ulong ToULong(this long v) => (ulong)v;
public static ushort ToUShort(this ulong v) => (ushort)v;
public static short ToShort(this ulong v) => (short)v;
public static int ToInt(this ulong v) => (int)v;
public static uint ToUInt(this ulong v) => (uint)v;
public static long ToLong(this ulong v) => (long)v;
public static short Swap(this short v)
{
return (short)(((v & 0xff) << 8) | ((v >> 8) & 0xff));
}
public static ushort Swap(this ushort v)
{
return (ushort)(((v & 0xff) << 8) | ((v >> 8) & 0xff));
}
public static int Swap(this int v)
{
return (int)(((Swap((short)v) & 0xffff) << 0x10) |
(Swap((short)(v >> 0x10)) & 0xffff));
}
public static uint Swap(this uint v)
{
return (uint)(((Swap((ushort)v) & 0xffff) << 0x10) |
(Swap((ushort)(v >> 0x10)) & 0xffff));
}
public static long Swap(this long v)
{
return (long)(((Swap((int)v) & 0xffffffffL) << 0x20) |
(Swap((int)(v >> 0x20)) & 0xffffffffL));
}
public static ulong Swap(this ulong v)
{
return (ulong)(((Swap((uint)v) & 0xffffffffL) << 0x20) |
(Swap((uint)(v >> 0x20)) & 0xffffffffL));
}
public static byte[] ToHexBytes(this string hexString)
{
hexString = hexString.Replace(" ", "");   //去除空格
            if ((hexString.Length % 2) != 0)     //判断hexstring的长度是否为偶数
            {
hexString += "";
}
byte[] returnBytes = new byte[hexString.Length / 2];  //声明一个长度为hexstring长度一半的字节组returnBytes
            for (int i = 0; i < returnBytes.Length; i++)
{
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);  //将hexstring的两个字符转换成16进制的字节组
            }
return returnBytes;
}
        //字节组转换成16进制的字符串:
        public static string ToHexStr(this byte[] bytes)
{
string returnStr = "";
if (bytes != null)
{
for (int i = 0; i < bytes.Length; i++)
{
returnStr += bytes[i].ToString("X2");      //byte转16进制字符
                }
}
return returnStr;
}
static ushort[] crc_table = new ushort[] { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 };
public static ushort ToCRC16(this byte[] buffer)
{
return ToShort16(buffer, (uint)buffer.Length, 0x00);
}
public static ushort ToShort16(this byte[] buffer, ushort precrc = 0x00)
{
return ToShort16(buffer, (uint)buffer.Length, precrc);
}
public static ushort ToShort16(this byte[] buffer, uint buffer_length, ushort precrc = 0x00)
{
ushort crc = precrc;
for (uint i = 0; i < buffer_length; i++)
{
crc = (ushort)(crc_table[((crc >> 8) ^ buffer[i]) & 0xFF] ^ (crc << 8));
}
return crc;
}
public static byte[] StructToBytes<T>(this T obj) where T : struct
{
int rawsize = Marshal.SizeOf<T>();
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.StructureToPtr(obj, buffer, true);
byte[] rawdatas = new byte[rawsize];
Marshal.Copy(buffer, rawdatas, 0, rawsize);
Marshal.FreeHGlobal(buffer);
return rawdatas;
}
public static T BytesToStruct<T>(this byte[] bytes) where T : struct
{
T obj = default(T);
Type anytype = typeof(T);
int rawsize = Marshal.SizeOf<T>();
if (bytes != null && bytes.Length >= rawsize)
{
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.Copy(bytes, 0, buffer, rawsize);
object retobj = Marshal.PtrToStructure(buffer, anytype);
Marshal.FreeHGlobal(buffer);
obj = (T)retobj;
}
return obj;
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
namespace IoTSharp.Extensions
{
public static class EnumerableExtensions
{
/// <summary>
/// 复制序列中的数据
/// </summary>
/// <typeparam name="T">泛型</typeparam>
/// <param name="iEnumberable">原数据</param>
/// <param name="startIndex">原数据开始复制的起始位置</param>
/// <param name="length">需要复制的数据长度</param>
/// <returns></returns>
public static IEnumerable<T> Copy<T>(this IEnumerable<T> iEnumberable, int startIndex, int length)
{
var sourceArray = iEnumberable.ToArray();
T[] newArray = new T[length];
Array.Copy(sourceArray, startIndex, newArray, 0, length);
return newArray;
}
/// <summary>
/// 给IEnumerable拓展ForEach方法
/// </summary>
/// <typeparam name="T">模型类</typeparam>
/// <param name="iEnumberable">数据源</param>
/// <param name="func">方法</param>
public static void ForEach<T>(this IEnumerable<T> iEnumberable, Action<T> func)
{
foreach (var item in iEnumberable)
{
func(item);
}
}
/// <summary>
/// 给IEnumerable拓展ForEach方法
/// </summary>
/// <typeparam name="T">模型类</typeparam>
/// <param name="iEnumberable">数据源</param>
/// <param name="func">方法</param>
public static void ForEach<T>(this IEnumerable<T> iEnumberable, Action<T, int> func)
{
var array = iEnumberable.ToArray();
for (int i = 0; i < array.Count(); i++)
{
func(array[i], i);
}
}
/// <summary>
/// IEnumerable转换为List'T'
/// </summary>
/// <typeparam name="T">参数</typeparam>
/// <param name="source">数据源</param>
/// <returns></returns>
public static List<T> CastToList<T>(this IEnumerable source)
{
return new List<T>(source.Cast<T>());
}
/// <summary>
/// 将IEnumerable'T'转为对应的DataTable
/// </summary>
/// <typeparam name="T">数据模型</typeparam>
/// <param name="iEnumberable">数据源</param>
/// <returns>DataTable</returns>
public static DataTable ToDataTable<T>(this IEnumerable<T> iEnumberable)
{
return iEnumberable.ToJson().ToDataTable();
}
public static IEnumerable<T[]> Chunk<T>(this IEnumerable<T> items, int size)
{
T[] array = items as T[] ?? items.ToArray();
for (int i = 0; i < array.Length; i += size)
{
T[] chunk = new T[Math.Min(size, array.Length - i)];
Array.Copy(array, i, chunk, 0, chunk.Length);
yield return chunk;
}
}
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> source, int chunkSize)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (chunkSize < 1)
{
throw new ArgumentException("Invalid chunkSize: " + chunkSize);
}
using (IEnumerator<T> sourceEnumerator = source.GetEnumerator())
{
IList<T> currentChunk = new List<T>();
while (sourceEnumerator.MoveNext())
{
currentChunk.Add(sourceEnumerator.Current);
if (currentChunk.Count == chunkSize)
{
yield return currentChunk;
currentChunk = new List<T>();
}
}
if (currentChunk.Any())
{
yield return currentChunk;
}
}
}
public static List<List<T>> Split2<T>(this List<T> source,int size)
{
return source
.Select((x, i) => new { Index = i, Value = x })
.GroupBy(x => x.Index / size)
.Select(x => x.Select(v => v.Value).ToList())
.ToList();
}
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int len)
{
if (len == 0)
throw new ArgumentNullException();
var enumer = source.GetEnumerator();
while (enumer.MoveNext())
{
yield return Take(enumer.Current, enumer, len);
}
}
private static IEnumerable<T> Take<T>(T head, IEnumerator<T> tail, int len)
{
while (true)
{
yield return head;
if (--len == 0)
break;
if (tail.MoveNext())
head = tail.Current;
else
break;
}
}
public static IEnumerable<IEnumerable<T>> Split3<T>(this List<T> source, int chunksize)
{
var chunk = new List<T>(chunksize);
List<List<T>> _source = new List<List<T>>();
_source.Add( source);
foreach (var element in _source.SelectMany(s => s))
{
if (chunksize == chunk.Count)
{
yield return chunk;
chunk = new List<T>(chunksize);
}
chunk.Add(element);
}
yield return chunk;
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace IoTSharp.Extensions
{
public static class FileExtension
{
/// <summary>
/// 如果文件存在, 则返回长度, 不存在, 则返回 0 。
/// </summary>
/// <param name="fi"></param>
/// <returns></returns>
public static long GetLength(this FileInfo fi) => fi.Exists ? fi.Length : 0;
/// <summary>
/// 使用 Filter列举文件
/// </summary>
/// <param name="directory"></param>
/// <param name="filesFilter"></param>
/// <param name="searchOption"></param>
/// <param name="limit">数量上限, 如果大于0 , 则表示只取列出的前<para>limit </para></param>
/// <returns></returns>
public static IEnumerable<string> EnumerateFilesFilter(this DirectoryInfo directory, string filesFilter, SearchOption searchOption = SearchOption.TopDirectoryOnly, int limit = -1)
{
if (limit == -1)
{
return filesFilter.Split(',', ';', '|').SelectMany(_ => Directory.EnumerateFiles(directory.FullName, "*" + _, searchOption));
}
else
{
List<string> lst = new List<string>();
foreach (var item in filesFilter.Split(',', ';', '|'))
{
lst.AddRange(Directory.EnumerateFiles(directory.FullName, item, searchOption).Take(limit));
if (lst.Count >= limit)
{
break;
}
}
return lst;
}
}
public static DriveInfo GetDriveInfo(this FileInfo file)
{
return new DriveInfo(file.Directory.Root.FullName);
}
/// <summary>
/// 获取文件的SHA1
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static string GetSHA1(this FileInfo s)
{
SHA1 sha1 = SHA1.Create() ;
byte[] retval = sha1.ComputeHash(s.ReadAllBytes());
string result = BitConverter.ToString(retval).Replace("-", "");
return result;
}
/// <summary>
/// 获取文件的MD5
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static string GetMd5Sum(this FileInfo s)
{
MD5 md5 = MD5.Create();
string t2 = BitConverter.ToString(md5.ComputeHash(s.ReadAllBytes()));
t2 = t2.Replace("-", "");
return t2;
}
public static byte[] ReadAllBytes(this FileInfo fi) => File.ReadAllBytes(fi.FullName);
public static byte[] ReadBytes(this FileInfo fi, int count) => ReadBytes(fi, 0, count);
public static byte[] ReadBytes(this FileInfo fi, int offset, int count)
{
byte[] buffer = new byte[count];
using (var fs = fi.OpenRead())
{
fs.Seek(offset, SeekOrigin.Begin);
fs.Read(buffer, 0, count);
}
return buffer;
}
public static void WriteAllText(this FileInfo fi, string contents) => File.WriteAllText(fi.FullName, contents);
public static bool Exists(this FileInfo fi) => File.Exists(fi.FullName);
public static void Delete(this FileInfo fi) => File.Delete(fi.FullName);
public static string ReadAllText(this FileInfo fi) => File.ReadAllText(fi.FullName);
public static void WriteAllBytes(this FileInfo fi, byte[] bytes) => File.WriteAllBytes(fi.FullName, bytes);
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>1.0.1</Version>
<Authors>MaikeBing</Authors>
<PackageIconUrl />
<PackageProjectUrl>https://github.com/IoTSharp/IoTSharp</PackageProjectUrl>
<RepositoryUrl>https://github.com/IoTSharp/IoTSharp</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>

using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Threading;
namespace IoTSharp.Extensions
{
public static class MiscExtensions
{
public static string MD5Sum(this string text) => BitConverter.ToString(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(text))).Replace("-", "");
}
}
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IoTSharp.Extensions
{
/// <summary>
/// 并行分区执行
/// </summary>
public static class ParallelPart
{
/// <summary>
/// 并行处理<paramref name="source"/>,一个并行任务中分配<paramref name="rangeSize"/>个元素给 <paramref name="action"/>
/// </summary>
/// <typeparam name="T">元素类型</typeparam>
/// <param name="source">源数据</param>
/// <param name="rangeSize">一个并行任务的最大分配数量</param>
/// <param name="parallelOptions"></param>
/// <param name="action"></param>
/// <returns></returns>
public static ParallelLoopResult ForEach<T>(IEnumerable<T> source, int rangeSize, ParallelOptions parallelOptions, Action<T> action)
{
return Parallel.ForEach(Partitioner.Create(0, source.Count(), Math.Min(source.Count(), rangeSize)), parallelOptions ?? new ParallelOptions(), (range, loopState) =>
{
for (int i = range.Item1; i < range.Item2; i++)
{
action?.Invoke(source.ElementAt(i));
}
});
}
/// <summary>
/// 并行处理<paramref name="source"/>,在任务分区处理时,每一个区同时通过<paramref name="factory"/>获取一个<typeparamref name="T1"/>对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="T1">针对每个分区的注入对象</typeparam>
/// <param name="source"></param>
/// <param name="options"></param>
/// <param name="factory"></param>
/// <param name="action"></param>
/// <returns></returns>
public static ParallelLoopResult ForEach<T, T1>(IEnumerable<T> source, ParallelOptions options, Action<T, T1> action)
=> ForEach<T, Action<T, T1>>(source, options, action);
/// <summary>
/// 并行处理<paramref name="source"/>,分为<paramref name="_maxDegreeOfParallelism"/>个区,每一个区同时通过<paramref name="factory"/>获取一个<typeparamref name="T1"/>对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="T1"></typeparam>
/// <param name="source"></param>
/// <param name="_maxDegreeOfParallelism"></param>
/// <param name="factory"></param>
/// <param name="action"></param>
/// <returns></returns>
public static ParallelLoopResult ForEach<T, T1>(IEnumerable<T> source, int _maxDegreeOfParallelism, Action<T, T1> action)
=> ForEach(source, new ParallelOptions() { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, action);
/// <summary>
/// 并行处理<paramref name="source"/>,分为<paramref name="_maxDegreeOfParallelism"/>个区,
/// 每一个区同时通过<paramref name="factory"/>获取<typeparamref name="T1"/>、<typeparamref name="T2"/>,并传递给<paramref name="action"/>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="T1"></typeparam>
/// <typeparam name="T2"></typeparam>
/// <param name="source"></param>
/// <param name="_maxDegreeOfParallelism"></param>
/// <param name="factory"></param>
/// <param name="action"></param>
/// <returns></returns>
public static ParallelLoopResult ForEach<T, T1, T2>(IEnumerable<T> source, int _maxDegreeOfParallelism, Action<T, T1, T2> action)
=> ForEach(source, new ParallelOptions() { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, action);
/// <summary>
/// 并行处理<paramref name="source"/>,分为<paramref name="_maxDegreeOfParallelism"/>个区,
/// 每一个区同时通过<paramref name="factory"/>获取<typeparamref name="T1"/>、<typeparamref name="T2"/>、<typeparamref name="T3"/>,并传递给<paramref name="action"/>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="T1"></typeparam>
/// <typeparam name="T2"></typeparam>
/// <typeparam name="T3"></typeparam>
/// <param name="source"></param>
/// <param name="_maxDegreeOfParallelism"></param>
/// <param name="factory"></param>
/// <param name="action"></param>
/// <returns></returns>
public static ParallelLoopResult ForEach<T, T1, T2,T3>(IEnumerable<T> source,int _maxDegreeOfParallelism , Action<T, T1, T2,T3> action)
=> ForEach(source, new ParallelOptions() { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, action);
/// <summary>
/// 并行处理<paramref name="source"/>,分为<paramref name="_maxDegreeOfParallelism"/>个区,
/// 每一个区同时通过<paramref name="factory"/>获取<typeparamref name="T1"/>、<typeparamref name="T2"/>、<typeparamref name="T3"/>、<typeparamref name="T4"/>,并传递给<paramref name="action"/>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="T1"></typeparam>
/// <typeparam name="T2"></typeparam>
/// <typeparam name="T3"></typeparam>
/// <typeparam name="T4"></typeparam>
/// <param name="source"></param>
/// <param name="_maxDegreeOfParallelism"></param>
/// <param name="factory"></param>
/// <param name="action"></param>
/// <returns></returns>
public static ParallelLoopResult ForEach<T, T1, T2,T3, T4>(IEnumerable<T> source, int _maxDegreeOfParallelism, Action<T, T1, T2, T3,T4> action)
=> ForEach(source, new ParallelOptions() { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, action);
public static ParallelLoopResult ForEach<T, T1, T2, T3,T4,T5>(IEnumerable<T> source, int _maxDegreeOfParallelism, Action<T, T1, T2, T3,T4,T5> action)
=> ForEach(source, new ParallelOptions() { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, action);
public static ParallelLoopResult ForEach<T, T1, T2, T3, T4, T5,T6>(IEnumerable<T> source, int _maxDegreeOfParallelism, Action<T, T1, T2, T3, T4, T5,T6> action)
=> ForEach(source, new ParallelOptions() { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, action);
public static ParallelLoopResult ForEach<T, T1, T2, T3, T4, T5,T6, T7>(IEnumerable<T> source, int _maxDegreeOfParallelism, Action<T, T1, T2, T3, T4, T5,T6, T7> action)
=> ForEach(source, new ParallelOptions() { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, action);
public static ParallelLoopResult ForEach<T, T1,T2>(IEnumerable<T> source, ParallelOptions parallelOptions, Action<T, T1, T2> action, Action<T1, T2> _init_action, Action<T1, T2> _finish_action)
{
return ForEach(source, parallelOptions, action, (Delegate)_init_action, _finish_action);
}
public static ParallelLoopResult ForEach<T, T1, T2,T3>(IEnumerable<T> source, ParallelOptions parallelOptions, Action<T, T1, T2,T3> action, Action<T1, T2> _init_action, Action<T1, T2,T3> _finish_action)
{
return ForEach(source, parallelOptions, action, (Delegate)_init_action, _finish_action);
}
public static ParallelLoopResult ForEach<T, T1, T2, T3,T4,T5,T6>(IEnumerable<T> source, int _maxDegreeOfParallelism, Action<T, T1, T2, T3, T4, T5, T6> action, Action<T1, T2, T3, T4, T5, T6> _init_action, Action<T1, T2, T3, T4, T5, T6> _finish_action)
{
return ForEach(source, new ParallelOptions() { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, action, (Delegate)_init_action, _finish_action);
}
public static ParallelLoopResult ForEach<T, T1, T2, T3,T4,T5>(IEnumerable<T> source, int _maxDegreeOfParallelism, Action<T, T1, T2, T3, T4, T5> action, Action<T1, T2, T3, T4, T5> _init_action, Action<T1, T2, T3, T4, T5> _finish_action)
{
return ForEach(source, new ParallelOptions() { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, action, (Delegate)_init_action, _finish_action);
}
public static ParallelLoopResult ForEach<T, T1, T2, T3, T4>(IEnumerable<T> source, int _maxDegreeOfParallelism, Action<T, T1, T2, T3, T4> action, Action<T1, T2, T3, T4> _init_action, Action<T1, T2, T3, T4> _finish_action)
{
return ForEach(source, new ParallelOptions() { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, action, (Delegate)_init_action, _finish_action);
}
public static ParallelLoopResult ForEach<T, T1, T2,T3>(IEnumerable<T> source, int _maxDegreeOfParallelism, Action<T, T1, T2,T3> action, Action<T1, T2,T3> _init_action, Action<T1, T2,T3> _finish_action)
{
return ForEach(source, new ParallelOptions() { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, action, (Delegate)_init_action, _finish_action);
}
public static ParallelLoopResult ForEach<T, T1, T2>(IEnumerable<T> source, int _maxDegreeOfParallelism, Action<T, T1, T2> action, Action<T1, T2> _init_action, Action<T1, T2> _finish_action)
{
return ForEach(source, new ParallelOptions() { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, action, (Delegate)_init_action, _finish_action);
}
public static ParallelLoopResult ForEach<T, T1>(IEnumerable<T> source, ParallelOptions parallelOptions, Action<T, T1> action, Action<T1> _init_action, Action<T1> _finish_action)
{
return ForEach(source, parallelOptions, action, (Delegate)_init_action, _finish_action);
}
public static ParallelLoopResult ForEach<T, A>(IEnumerable<T> source, ParallelOptions parallelOptions, A action) where A : Delegate
{
return ForEach<T, A, A>(source, parallelOptions, action, null, null);
}
private static ParallelLoopResult ForEach<T, A, B>(IEnumerable<T> source, ParallelOptions parallelOptions, A action, B _init_action, B _finish_action) where A : Delegate, B where B : Delegate
{
int rangeSize = parallelOptions.MaxDegreeOfParallelism ==1? source.Count() : (source.Count() + parallelOptions.MaxDegreeOfParallelism - 1) / parallelOptions.MaxDegreeOfParallelism;
return Parallel.ForEach(Partitioner.Create(0, source.Count(), Math.Min(source.Count(), rangeSize)), parallelOptions ?? new ParallelOptions(), (range, loopState) =>
{
List<object> list = new List<object>();
action.GetType().GenericTypeArguments.Skip(1).ToList().ForEach(t =>
{
list.Add(Activator.CreateInstance(t));
});
_init_action?.DynamicInvoke(list.ToArray());
for (int i = range.Item1; i < range.Item2; i++)
{
var objs = new List<object>();
objs.Add(source.ElementAt(i));
objs.AddRange(list);
action.DynamicInvoke(objs.ToArray());
}
_finish_action?.DynamicInvoke(list.ToArray());
});
}
/// <summary>
/// 并行处理<paramref name="source"/>,按照最多<paramref name="_maxDegreeOfParallelism"/>个个数分配元素给<paramref name="action"/>处理
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="_maxDegreeOfParallelism">最大任务量</param>
/// <param name="action"></param>
/// <returns></returns>
public static ParallelLoopResult ForEach<T>(IEnumerable<T> source, int _maxDegreeOfParallelism, Action<T> action) =>
ForEach(source, (source.Count() + _maxDegreeOfParallelism - 1) / _maxDegreeOfParallelism, new ParallelOptions() { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, action);
/// <summary>
/// 并行处理<paramref name="source"/>给<paramref name="action"/>处理
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="action"></param>
/// <returns></returns>
public static ParallelLoopResult ForEach<T>(IEnumerable<T> source, Action<T> action)
{
ParallelOptions parallelOptions = new ParallelOptions();
return ForEach(source, (source.Count() + parallelOptions.MaxDegreeOfParallelism - 1) / parallelOptions.MaxDegreeOfParallelism, parallelOptions, action);
}
public static ParallelLoopResult ForEach<T>(IEnumerable<T> source, ParallelOptions parallelOptions, Action<T> action) =>
ForEach(source, (source.Count() + parallelOptions.MaxDegreeOfParallelism - 1) / parallelOptions.MaxDegreeOfParallelism, parallelOptions, action);
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace IoTSharp.Extensions
{
/// <summary>
/// 重试类
/// </summary>
public static class Retry
{
[Obsolete("已放弃,请调用T RetryOnAny<T>(int times, Func<T> action)")]
public static T Invoke<T>(int times, Func<T> action)
{
return RetryOnAny(times, action);
}
/// <summary>
/// 无论遇到任何错误,最多尝试<paramref name="times"/>次
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="times"></param>
/// <param name="action"></param>
/// <returns></returns>
public static T RetryOnAny<T>(int times, Func<T> action)
{
return RetryOnAny(times, a =>
{
return action.Invoke();
}, ef =>
{
Thread.Sleep(TimeSpan.FromSeconds(ef.current * 5));
});
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="times"></param>
/// <param name="action"></param>
/// <param name="efunc"></param>
/// <returns></returns>
[Obsolete("放弃,请调用RetryOnAny(int times, Func<int, T> action, Action<(int current, Exception ex)> efunc)")]
public static T Invoke<T>(int times, Func<int, T> action, Action<(int current, Exception ex)> efunc)
{
return RetryOnAny(times, action, efunc);
}
/// <summary>
/// 当遇到<typeparamref name="E"/>的异常时重试指定<paramref name="times"/>次,遇到其他异常则认为失败。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="E"></typeparam>
/// <param name="times"></param>
/// <param name="action"></param>
/// <param name="efunc"></param>
/// <returns></returns>
public static T RetryOnException<T, E>(int times, Func<int, T> action, Action<(int current, Exception ex)> efunc) where E : Exception
{
Exception exception = null;
for (int i = 0; i < times; i++)
{
try
{
try
{
return action.Invoke(i + 1);
}
catch (E)
{
}
}
catch (Exception ex)
{
exception = ex;
break;
}
}
throw exception;
}
/// <summary>
/// 重试指定任务,除非遇到异常<typeparamref name="E"/>就不再重试
/// </summary>
/// <typeparam name="T">返回值</typeparam>
/// <typeparam name="E">遇到此异常不再重试</typeparam>
/// <param name="times">次数</param>
/// <param name="action">调用的方法</param>
/// <param name="efunc"></param>
/// <returns></returns>
public static T RetryUnlessException<T, E>(int times, Func<int, T> action) where E : Exception
{
Exception exception = null;
for (int i = 0; i < times; i++)
{
try
{
try
{
return action.Invoke(i + 1);
}
catch (E ex)
{
exception = ex;
break;
}
}
catch (Exception)
{
}
}
throw exception;
}
public static T RetryOnAny<T>(int times, Func<int, T> action, Action<(int current, Exception ex)> efunc)
{
Exception exception = null;
for (int i = 0; i < times; i++)
{
try
{
return action.Invoke(i + 1);
}
catch (Exception ex)
{
exception = ex;
efunc?.Invoke((i + 1, ex));
}
}
throw exception;
}
public static T RetryOnAny<T>(int times, Func<T> action, Action<(int current, Exception ex)> efunc)
{
Exception exception = null;
for (int i = 0; i < times; i++)
{
try
{
return action.Invoke();
}
catch (Exception ex)
{
exception = ex;
efunc?.Invoke((i + 1, ex));
}
}
throw exception;
}
}
}
此差异已折叠。
using System;
using System.Threading.Tasks;
namespace IoTSharp.Extensions
{
public static class TaskExtension
{
public static Task Forget(this Task task)
{
return Task.CompletedTask;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IoTSharp.Extensions
{
public static class TypeExtensions
{
public static bool IsSqlSimpleType(this Type type)
{
var t = type;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
t = Nullable.GetUnderlyingType(type);
return t.IsPrimitive || t.Equals(typeof(string)) ||
t.Equals(typeof(DateTime)) || t.Equals(typeof(DateTimeOffset)) || t.Equals(typeof(TimeSpan)) ||
t.Equals(typeof(Guid)) ||
t.Equals(typeof(byte[])) || t.Equals(typeof(char[]));
}
public static bool IsTupleType(this Type type, bool checkBaseTypes = false)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
if (type == typeof(Tuple))
return true;
if (type == typeof(ValueTuple))
return true;
while (type != null)
{
if (type.IsGenericType)
{
var genType = type.GetGenericTypeDefinition();
if (genType == typeof(Tuple<>)
|| genType == typeof(Tuple<,>)
|| genType == typeof(Tuple<,,>)
|| genType == typeof(Tuple<,,,>)
|| genType == typeof(Tuple<,,,,>)
|| genType == typeof(Tuple<,,,,,>)
|| genType == typeof(Tuple<,,,,,,>)
|| genType == typeof(Tuple<,,,,,,,>)
|| genType == typeof(Tuple<,,,,,,,>))
return true;
if (genType == typeof(ValueTuple<>)
|| genType == typeof(ValueTuple<,>)
|| genType == typeof(ValueTuple<,,>)
|| genType == typeof(ValueTuple<,,,>)
|| genType == typeof(ValueTuple<,,,,>)
|| genType == typeof(ValueTuple<,,,,,>)
|| genType == typeof(ValueTuple<,,,,,,>)
|| genType == typeof(ValueTuple<,,,,,,,>)
|| genType == typeof(ValueTuple<,,,,,,,>))
return true;
}
if (!checkBaseTypes)
break;
type = type.BaseType;
}
return false;
}
}
}

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
namespace IoTSharp.Extensions
{
public static class XmlExtensions
{
public static bool XML2Json(System.IO.MemoryStream xml, out object obj)
{
bool ok = false;
obj = null;
try
{
XmlDocument doc = new XmlDocument();
xml.Seek(0, System.IO.SeekOrigin.Begin);
doc.Load(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc.DocumentElement);
obj = JsonConvert.DeserializeObject(jsonText);
ok = true;
}
catch (Exception)
{
}
return ok;
}
public static bool XML2Json(FileInfo xml, out object obj)
{
bool ok = false;
obj = null;
try
{
XmlDocument doc = new XmlDocument();
doc.Load(xml.FullName);
string jsonText = JsonConvert.SerializeXmlNode(doc.DocumentElement);
obj = JsonConvert.DeserializeObject(jsonText);
ok = true;
}
catch (Exception)
{
}
return ok;
}
public static bool XML2Json(string xml, out object obj)
{
bool ok = false;
obj = null;
try
{
if (!IsValidXmlString(xml))
{
xml = RemoveInvalidXmlChars(xml);
}
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc.DocumentElement);
obj = JsonConvert.DeserializeObject(jsonText);
ok = true;
}
catch (Exception)
{
}
return ok;
}
private static string RemoveInvalidXmlChars(string text)
{
var validXmlChars = text.Where(ch => XmlConvert.IsXmlChar(ch)).ToArray();
return new string(validXmlChars);
}
private static bool IsValidXmlString(string text)
{
try
{
XmlConvert.VerifyXmlChars(text);
return true;
}
catch
{
return false;
}
}
public static List<T> ToList<T>(this List<System.Xml.Linq.XElement> _Nodes)
{
if (_Nodes == null)
{
throw new ArgumentNullException(nameof(_Nodes));
}
List<T> ts = new List<T>();
try
{
var ems = from ex in _Nodes where ex.Name.LocalName == "diffgram" select ex;
ems.ToList().ForEach(em =>
{
var emls = from exx in em.Elements().FirstOrDefault(xe => xe.Name.LocalName == typeof(T).Name).Elements() select JObject.FromObject(exx).GetValue("Table").ToObject<T>();
ts.AddRange(emls.ToArray());
});
}
catch (Exception)
{
}
return ts;
}
}
}
......@@ -81,6 +81,20 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MQTTRouting", "MQTTRouting"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DataStorage", "DataStorage", "{2FC499CB-B5FB-4F71-A396-7B85A3FA3115}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IoTSharp.Data.TimeSeries", "IoTSharp.Data.TimeSeries\IoTSharp.Data.TimeSeries.csproj", "{C28D5462-79CE-4772-AAFA-58C4F059625A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IoTSharp.Contracts", "IoTSharp.Contracts\IoTSharp.Contracts.csproj", "{46CF0B8D-87AC-45FE-A05A-2F80B163349B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IoTSharp.Extensions", "IoTSharp.Extensions\IoTSharp.Extensions.csproj", "{759B6A90-E00E-494F-A563-3D4549C9769B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IoTSharp.Extensions.AspNetCore", "IoTSharp.Extensions.AspNetCore\IoTSharp.Extensions.AspNetCore.csproj", "{C9E2CA32-BD7D-4894-87E5-F1570BABF2AD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IoTSharp.Extensions.EFCore", "IoTSharp.Extensions.EFCore\IoTSharp.Extensions.EFCore.csproj", "{359F092E-D96A-42EA-8BB7-BAD014269D36}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IoTSharp.Extensions.BouncyCastle", "IoTSharp.Extensions.BouncyCastle\IoTSharp.Extensions.BouncyCastle.csproj", "{94B2685D-DE46-4125-8164-ED7DD91AD650}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IoTSharp.Extensions.RESTful", "IoTSharp.Extensions.RESTful\IoTSharp.Extensions.RESTful.csproj", "{05890E8E-0A6C-469C-AF20-7E789992662F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -159,6 +173,34 @@ Global
{5A80EC19-D6AC-4CE0-9DA0-026C7C7C5282}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5A80EC19-D6AC-4CE0-9DA0-026C7C7C5282}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5A80EC19-D6AC-4CE0-9DA0-026C7C7C5282}.Release|Any CPU.Build.0 = Release|Any CPU
{C28D5462-79CE-4772-AAFA-58C4F059625A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C28D5462-79CE-4772-AAFA-58C4F059625A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C28D5462-79CE-4772-AAFA-58C4F059625A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C28D5462-79CE-4772-AAFA-58C4F059625A}.Release|Any CPU.Build.0 = Release|Any CPU
{46CF0B8D-87AC-45FE-A05A-2F80B163349B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{46CF0B8D-87AC-45FE-A05A-2F80B163349B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46CF0B8D-87AC-45FE-A05A-2F80B163349B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46CF0B8D-87AC-45FE-A05A-2F80B163349B}.Release|Any CPU.Build.0 = Release|Any CPU
{759B6A90-E00E-494F-A563-3D4549C9769B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{759B6A90-E00E-494F-A563-3D4549C9769B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{759B6A90-E00E-494F-A563-3D4549C9769B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{759B6A90-E00E-494F-A563-3D4549C9769B}.Release|Any CPU.Build.0 = Release|Any CPU
{C9E2CA32-BD7D-4894-87E5-F1570BABF2AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C9E2CA32-BD7D-4894-87E5-F1570BABF2AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9E2CA32-BD7D-4894-87E5-F1570BABF2AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C9E2CA32-BD7D-4894-87E5-F1570BABF2AD}.Release|Any CPU.Build.0 = Release|Any CPU
{359F092E-D96A-42EA-8BB7-BAD014269D36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{359F092E-D96A-42EA-8BB7-BAD014269D36}.Debug|Any CPU.Build.0 = Debug|Any CPU
{359F092E-D96A-42EA-8BB7-BAD014269D36}.Release|Any CPU.ActiveCfg = Release|Any CPU
{359F092E-D96A-42EA-8BB7-BAD014269D36}.Release|Any CPU.Build.0 = Release|Any CPU
{94B2685D-DE46-4125-8164-ED7DD91AD650}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{94B2685D-DE46-4125-8164-ED7DD91AD650}.Debug|Any CPU.Build.0 = Debug|Any CPU
{94B2685D-DE46-4125-8164-ED7DD91AD650}.Release|Any CPU.ActiveCfg = Release|Any CPU
{94B2685D-DE46-4125-8164-ED7DD91AD650}.Release|Any CPU.Build.0 = Release|Any CPU
{05890E8E-0A6C-469C-AF20-7E789992662F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{05890E8E-0A6C-469C-AF20-7E789992662F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{05890E8E-0A6C-469C-AF20-7E789992662F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{05890E8E-0A6C-469C-AF20-7E789992662F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
......@@ -18,8 +18,7 @@ using System.Threading.Tasks;
using IoTSharp.Controllers.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Silkier.AspNetCore;
using Silkier.Extensions;
using Jdenticon.AspNetCore;
namespace IoTSharp.Controllers
......
using DotNetCore.CAP;
using EasyCaching.Core;
using IoTSharp.Contracts;
using IoTSharp.Controllers.Models;
using IoTSharp.Data;
using IoTSharp.Dtos;
......
......@@ -373,7 +373,7 @@ namespace IoTSharp.Controllers
rule.DefinitionsXml = m.Xml;
rule.Creator = profile.Id.ToString();
rule.CreateId = CreatorId;
_context.Flows.Where(c => c.FlowRule.RuleId == rule.RuleId).ForEach(c =>
_context.Flows.Where(c => c.FlowRule.RuleId == rule.RuleId).ToList().ForEach(c =>
{
c.FlowStatus = -1;
});
......
using EFCore.Sharding;
namespace IoTSharp
{
public class ShardingSetting
{
public DatabaseType DatabaseType { get; set; } = DatabaseType.PostgreSql;
public ExpandByDateMode ExpandByDateMode { get; set; } = ExpandByDateMode.PerMonth;
}
}
......@@ -3,52 +3,10 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
namespace IoTSharp.Dtos
{
public class TelemetryDataDto
{
public string KeyName { get; set; }
public DateTime DateTime { get; set; }
public Data.DataType DataType { get; set; }
public object Value { get; set; }
}
public class TimespanConverterNewtonsoft : Newtonsoft.Json.JsonConverter<TimeSpan>
{
/// <summary>
/// Format: Days.Hours:Minutes:Seconds:Milliseconds
/// </summary>
public const string TimeSpanFormatString = @"d\.hh\:mm\:ss\:FFF";
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, TimeSpan value, Newtonsoft.Json.JsonSerializer serializer)
{
var timespanFormatted = $"{value.ToString(TimeSpanFormatString)}";
writer.WriteValue(timespanFormatted);
}
public override TimeSpan ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, TimeSpan existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
TimeSpan parsedTimeSpan;
TimeSpan.TryParseExact((string)reader.Value, TimeSpanFormatString, null, out parsedTimeSpan);
return parsedTimeSpan;
}
}
public class TimeSpanConverter : System.Text.Json.Serialization.JsonConverter<TimeSpan>
{
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return TimeSpan.Parse(reader.GetString());
}
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
/// <summary>
/// 查询历史遥测数据请求结构体
......
using System;
using System.Text.Json;
namespace IoTSharp.Dtos
{
public class TimeSpanConverter : System.Text.Json.Serialization.JsonConverter<TimeSpan>
{
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return TimeSpan.Parse(reader.GetString());
}
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
}
using System;
namespace IoTSharp.Dtos
{
public class TimespanConverterNewtonsoft : Newtonsoft.Json.JsonConverter<TimeSpan>
{
/// <summary>
/// Format: Days.Hours:Minutes:Seconds:Milliseconds
/// </summary>
public const string TimeSpanFormatString = @"d\.hh\:mm\:ss\:FFF";
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, TimeSpan value, Newtonsoft.Json.JsonSerializer serializer)
{
var timespanFormatted = $"{value.ToString(TimeSpanFormatString)}";
writer.WriteValue(timespanFormatted);
}
public override TimeSpan ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, TimeSpan existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
{
TimeSpan parsedTimeSpan;
TimeSpan.TryParseExact((string)reader.Value, TimeSpanFormatString, null, out parsedTimeSpan);
return parsedTimeSpan;
}
}
}
......@@ -19,7 +19,6 @@ using MQTTnet.Diagnostics;
using NSwag;
using NSwag.Generation.AspNetCore;
using NSwag.Generation.Processors.Security;
using Silkier.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
......
......@@ -17,11 +17,13 @@ using System.Security.Cryptography.X509Certificates;
using MQTTnet;
using MQTTnet.AspNetCore.Routing;
using IoTSharp.Data;
using Newtonsoft.Json.Linq;
namespace IoTSharp
{
public static class MqttExtension
{
//static private IMqttServer _mqttServer;
public static void AddIoTSharpMqttServer(this IServiceCollection services, MqttBrokerSetting broker)
{
......@@ -75,9 +77,12 @@ namespace IoTSharp
});
}
public static Dictionary<string, object> ConvertPayloadToDictionary(this MqttApplicationMessage msg)
{
return JToken.Parse(msg.ConvertPayloadToString() ?? "{}")?.JsonToDictionary();
}
public static async Task PublishAsync<T>(this MqttServer mqtt, string SenderClientId, string topic, T _payload) where T : class
{
......
此差异已折叠。
using DotNetCore.CAP;
using EasyCaching.Core;
using IoTSharp.Contracts;
using IoTSharp.Data;
using IoTSharp.Dtos;
using IoTSharp.Extensions;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册