feat: 改用Mapperly源生成,代替Mapster

This commit is contained in:
2248356998 qq.com
2025-06-28 00:00:43 +08:00
parent 6427ee6ee0
commit 77bfabc41d
98 changed files with 967 additions and 943 deletions

View File

@@ -17,8 +17,7 @@
</PropertyGroup>
<ItemGroup>
<None Include="$(OutputPath)\$(TargetFileName)" Pack="true"
PackagePath="analyzers/dotnet/cs" Visible="false" />
<None Include="$(OutputPath)\$(TargetFileName)" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
</ItemGroup>
@@ -27,6 +26,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" PrivateAssets="all" Private="false" />
</ItemGroup>
</Project>

View File

@@ -1,63 +1,48 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Text;
namespace Microsoft.AspNetCore.Components;
[Generator]
public partial class SetParametersAsyncGenerator : ISourceGenerator
public sealed partial class SetParametersAsyncGenerator : IIncrementalGenerator
{
private const string m_DoNotGenerateSetParametersAsyncAttribute = """
using System;
namespace Microsoft.AspNetCore.Components
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
internal sealed class DoNotGenerateSetParametersAsyncAttribute : Attribute { }
}
""";
private string m_DoNotGenerateSetParametersAsyncAttribute = """
using System;
namespace Microsoft.AspNetCore.Components
private const string m_GenerateSetParametersAsyncAttribute = """
using System;
namespace Microsoft.AspNetCore.Components
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
internal sealed class GenerateSetParametersAsyncAttribute : Attribute
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
internal sealed class DoNotGenerateSetParametersAsyncAttribute : Attribute
{
}
public bool RequireExactMatch { get; set; }
}
}
""";
"""
;
private string m_GenerateSetParametersAsyncAttribute = """
using System;
namespace Microsoft.AspNetCore.Components
private const string m_GlobalGenerateSetParametersAsyncAttribute = """
using System;
namespace Microsoft.AspNetCore.Components
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
internal sealed class GlobalGenerateSetParametersAsyncAttribute : Attribute
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
internal sealed class GenerateSetParametersAsyncAttribute : Attribute
{
public bool RequireExactMatch { get; set; }
}
public bool Enable { get; }
public GlobalGenerateSetParametersAsyncAttribute(bool enable = true) { Enable = enable; }
}
"""
;
private string m_GlobalGenerateSetParametersAsyncAttribute = """
using System;
namespace Microsoft.AspNetCore.Components
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
internal sealed class GlobalGenerateSetParametersAsyncAttribute : Attribute
{
public bool Enable { get; }
public GlobalGenerateSetParametersAsyncAttribute(bool enable = true)
{
Enable = enable;
}
}
}
"""
;
}
""";
private static readonly DiagnosticDescriptor ParameterNameConflict = new DiagnosticDescriptor(
id: "TG0001",
@@ -68,36 +53,64 @@ public partial class SetParametersAsyncGenerator : ISourceGenerator
isEnabledByDefault: true,
description: "Parameter names must be case insensitive to be usable in routes. Rename the parameter to not be in conflict with other parameters.");
public void Initialize(GeneratorInitializationContext context)
public void Initialize(IncrementalGeneratorInitializationContext context)
{
context.RegisterForPostInitialization(a =>
// 注入 attribute 源码
context.RegisterPostInitializationOutput(ctx =>
{
a.AddSource(nameof(m_DoNotGenerateSetParametersAsyncAttribute), m_DoNotGenerateSetParametersAsyncAttribute);
a.AddSource(nameof(m_GenerateSetParametersAsyncAttribute), m_GenerateSetParametersAsyncAttribute);
a.AddSource(nameof(m_GlobalGenerateSetParametersAsyncAttribute), m_GlobalGenerateSetParametersAsyncAttribute);
ctx.AddSource("DoNotGenerateSetParametersAsyncAttribute.g.cs", SourceText.From(m_DoNotGenerateSetParametersAsyncAttribute, Encoding.UTF8));
ctx.AddSource("GenerateSetParametersAsyncAttribute.g.cs", SourceText.From(m_GenerateSetParametersAsyncAttribute, Encoding.UTF8));
ctx.AddSource("GlobalGenerateSetParametersAsyncAttribute.g.cs", SourceText.From(m_GlobalGenerateSetParametersAsyncAttribute, Encoding.UTF8));
});
// Register a syntax receiver that will be created for each generation pass
context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
// 筛选 ClassDeclarationSyntax
var classDeclarations = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: static (node, _) => node is ClassDeclarationSyntax,
transform: static (ctx, _) => (ClassDeclarationSyntax)ctx.Node)
.Where(static c => c is not null);
// 合并 Compilation
var compilationProvider = context.CompilationProvider;
var candidateClasses = classDeclarations.Combine(compilationProvider);
context.RegisterSourceOutput(candidateClasses, static (spc, tuple) =>
{
var (classDeclaration, compilation) = tuple;
Execute(spc, compilation, classDeclaration);
});
}
public void Execute(GeneratorExecutionContext context)
private static void Execute(SourceProductionContext context, Compilation compilation, ClassDeclarationSyntax classDeclaration)
{
// https://github.com/dotnet/AspNetCore.Docs/blob/1e199f340780f407a685695e6c4d953f173fa891/aspnetcore/blazor/webassembly-performance-best-practices.md#implement-setparametersasync-manually
if (context.SyntaxReceiver is not SyntaxReceiver receiver)
{
var model = compilation.GetSemanticModel(classDeclaration.SyntaxTree);
var classSymbol = model.GetDeclaredSymbol(classDeclaration);
if (classSymbol is null || classSymbol.Name == "_Imports")
return;
}
var candidate_classes = GetCandidateClasses(receiver, context);
var positiveAttr = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.GenerateSetParametersAsyncAttribute");
var negativeAttr = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.DoNotGenerateSetParametersAsyncAttribute");
foreach (var class_symbol in candidate_classes.Distinct(SymbolEqualityComparer.Default).Cast<INamedTypeSymbol>())
{
GenerateSetParametersAsyncMethod(context, class_symbol);
}
if (classSymbol.GetAttributes().Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, negativeAttr)))
return;
if (!IsPartial(classSymbol) || !IsComponent(classDeclaration, classSymbol, compilation))
return;
var globalEnable = compilation.Assembly.GetAttributes()
.FirstOrDefault(a => a.AttributeClass?.ToDisplayString() == "Microsoft.AspNetCore.Components.GlobalGenerateSetParametersAsyncAttribute")
?.ConstructorArguments.FirstOrDefault().Value as bool? ?? false;
var hasPositive = classSymbol.GetAttributes().Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, positiveAttr));
if (!globalEnable && !hasPositive)
return;
GenerateSetParametersAsyncMethod(context, classSymbol);
}
private static void GenerateSetParametersAsyncMethod(GeneratorExecutionContext context, INamedTypeSymbol class_symbol)
private static void GenerateSetParametersAsyncMethod(SourceProductionContext context, INamedTypeSymbol class_symbol)
{
var force_exact_match = class_symbol.GetAttributes().Any(a => a.NamedArguments.Any(na => na.Key == "RequireExactMatch" && na.Value.Value is bool v && v));
var namespaceName = class_symbol.ContainingNamespace.ToDisplayString();
@@ -386,6 +399,31 @@ namespace {namespaceName}
#pragma warning restore CS0162");
}
private static bool IsPartial(INamedTypeSymbol symbol)
{
return symbol.DeclaringSyntaxReferences
.Select(r => r.GetSyntax())
.OfType<ClassDeclarationSyntax>()
.Any(c => c.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)));
}
private static bool IsComponent(ClassDeclarationSyntax classDeclaration, INamedTypeSymbol symbol, Compilation compilation)
{
if (HasUserDefinedSetParametersAsync(symbol))
return false;
if (classDeclaration.SyntaxTree.FilePath.EndsWith(".razor") || classDeclaration.SyntaxTree.FilePath.EndsWith(".razor.cs"))
return true;
var iComponent = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.IComponent");
var componentBase = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.ComponentBase");
if (iComponent == null || componentBase == null)
return false;
return symbol.AllInterfaces.Contains(iComponent) || SymbolEqualityComparer.Default.Equals(symbol.BaseType, componentBase);
}
private static bool HasUserDefinedSetParametersAsync(INamedTypeSymbol classSymbol)
{
return classSymbol
@@ -398,137 +436,4 @@ namespace {namespaceName}
!m.IsStatic);
}
private static bool IsPartial(INamedTypeSymbol symbol)
{
return symbol.DeclaringSyntaxReferences
.Select(r => r.GetSyntax())
.OfType<ClassDeclarationSyntax>()
.Any(c => c.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)));
}
private static bool IsComponent(ClassDeclarationSyntax classDeclarationSyntax, INamedTypeSymbol symbol, Compilation compilation)
{
if (HasUserDefinedSetParametersAsync(symbol))
{
// 用户自己写了方法,不生成
return false;
}
if (!IsPartial(symbol))
{
return false;
}
if (classDeclarationSyntax.SyntaxTree.FilePath.EndsWith(".razor") || classDeclarationSyntax.SyntaxTree.FilePath.EndsWith(".razor.cs"))
{
return true;
}
var iComponent = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.IComponent");
var componentBase = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.ComponentBase");
if (iComponent == null || componentBase == null)
return false;
if (SymbolEqualityComparer.Default.Equals(symbol, iComponent))
return true;
if (SymbolEqualityComparer.Default.Equals(symbol, componentBase))
return true;
return false;
}
/// <summary>
/// Enumerate methods with at least one Group attribute
/// </summary>
private static IEnumerable<INamedTypeSymbol> GetCandidateClasses(SyntaxReceiver receiver, GeneratorExecutionContext context)
{
var compilation = context.Compilation;
var positiveAttributeSymbol = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.GenerateSetParametersAsyncAttribute");
var negativeAttributeSymbol = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Components.DoNotGenerateSetParametersAsyncAttribute");
// loop over the candidate methods, and keep the ones that are actually annotated
// 找特性
var assemblyAttributes = compilation.Assembly.GetAttributes();
var enableAttr = assemblyAttributes.FirstOrDefault(attr =>
attr.AttributeClass?.ToDisplayString() == "Microsoft.AspNetCore.Components.GlobalGenerateSetParametersAsyncAttribute");
var globalEnable = false;
if (enableAttr != null)
{
var arg = enableAttr.ConstructorArguments.FirstOrDefault();
if (arg.Value is bool b)
globalEnable = b;
}
foreach (ClassDeclarationSyntax class_declaration in receiver.CandidateClasses)
{
var model = compilation.GetSemanticModel(class_declaration.SyntaxTree);
var class_symbol = model.GetDeclaredSymbol(class_declaration);
if (class_symbol is null)
{
continue;
}
if (class_symbol.Name == "_Imports")
{
continue;
}
// 是否拒绝生成
var hasNegative = class_symbol.GetAttributes().Any(ad =>
ad.AttributeClass?.Equals(negativeAttributeSymbol, SymbolEqualityComparer.Default) == true);
if (hasNegative)
continue;
if (IsComponent(class_declaration, class_symbol, compilation))
{
if (globalEnable)
{
yield return class_symbol;
}
else
{
// 必须显式标注 Positive Attribute
var hasPositive = class_symbol.GetAttributes().Any(ad =>
ad.AttributeClass?.Equals(positiveAttributeSymbol, SymbolEqualityComparer.Default) == true);
if (hasPositive)
yield return class_symbol;
}
}
else
{
}
}
}
/// <summary>
/// Created on demand before each generation pass
/// </summary>
internal class SyntaxReceiver : ISyntaxReceiver
{
public List<ClassDeclarationSyntax> CandidateClasses { get; } = new List<ClassDeclarationSyntax>();
/// <summary>
/// Called for every syntax node in the compilation, we can inspect the nodes and save any information useful for generation
/// </summary>
public void OnVisitSyntaxNode(SyntaxNode syntax_node)
{
// any class with at least one attribute is a candidate for property generation
if (syntax_node is ClassDeclarationSyntax classDeclarationSyntax)
{
CandidateClasses.Add(classDeclarationSyntax);
}
else
{
}
}
}
}

View File

@@ -7,7 +7,7 @@ namespace Microsoft.AspNetCore.Components
{
internal static class SourceGeneratorContextExtension
{
public static void AddCode(this GeneratorExecutionContext context, string hint_name, string code)
public static void AddCode(this SourceProductionContext context, string hint_name, string code)
{
context.AddSource(hint_name.Replace("<", "_").Replace(">", "_"), SourceText.From(code, Encoding.UTF8));
}

View File

@@ -1,13 +0,0 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
namespace Microsoft.AspNetCore.Components
{
internal static class StringExtension
{
public static string NormalizeWhitespace(this string code)
{
return CSharpSyntaxTree.ParseText(code).GetRoot().NormalizeWhitespace().ToFullString();
}
}
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -41,9 +39,9 @@ public class OpenApiController : ControllerBase
[AllowAnonymous]
public async Task<OpenApiLoginOutput> LoginAsync([FromBody] OpenApiLoginInput input)
{
var output = await _authService.LoginAsync(input.Adapt<LoginInput>(), false).ConfigureAwait(false);
var output = await _authService.LoginAsync(input.AdaptLoginInput(), false).ConfigureAwait(false);
var openApiLoginOutput = output.Adapt<OpenApiLoginOutput>();
var openApiLoginOutput = output.AdaptOpenApiLoginOutput();
return openApiLoginOutput;
}

View File

@@ -10,7 +10,7 @@
using BootstrapBlazor.Components;
using Mapster;
using Riok.Mapperly.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
@@ -31,7 +31,7 @@ public class SysUser : BaseEntity
///</summary>
[SugarColumn(ColumnDescription = "头像", ColumnDataType = StaticConfig.CodeFirst_BigString, IsNullable = true)]
[AutoGenerateColumn(Visible = true, Sortable = false, Filterable = false)]
[AdaptIgnore]
[MapperIgnore]
public virtual string? Avatar { get; set; }
/// <summary>

View File

@@ -0,0 +1,33 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
//------------------------------------------------------------------------------
using BootstrapBlazor.Components;
using Riok.Mapperly.Abstractions;
namespace ThingsGateway.Admin.Application;
[Mapper(UseDeepCloning = true, EnumMappingStrategy = EnumMappingStrategy.ByName, RequiredMappingStrategy = RequiredMappingStrategy.None)]
public static partial class AdminMapper
{
public static partial LoginInput AdaptLoginInput(this OpenApiLoginInput src);
public static partial OpenApiLoginOutput AdaptOpenApiLoginOutput(this LoginOutput src);
public static partial SessionOutput AdaptSessionOutput(this SysUser src);
public static partial SysUser AdaptSysUser(this SysUser src);
public static partial UserSelectorOutput AdaptUserSelectorOutput(this SysUser src);
public static partial List<SysResource> AdaptListSysResource(this IEnumerable<SysResource> src);
public static partial AppConfig AdaptAppConfig(this AppConfig src);
public static partial WorkbenchInfo AdaptWorkbenchInfo(this WorkbenchInfo src);
public static partial QueryData<UserSelectorOutput> AdaptQueryDataUserSelectorOutput(this QueryData<SysUser> src);
public static partial LoginInput AdaptLoginInput(this LoginInput src);
}

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using ThingsGateway.SqlSugar;
namespace ThingsGateway.Admin.Application;
@@ -69,7 +67,7 @@ internal sealed class SessionService : BaseService<SysUser>, ISessionService
var r = items.Select((it) =>
{
var reuslt = it.Adapt<SessionOutput>();
var reuslt = it.AdaptSessionOutput();
if (verificatInfoDicts.TryGetValue(it.Id, out var verificatInfos))
{
reuslt.VerificatCount = verificatInfos.Count;//令牌数量
@@ -94,7 +92,7 @@ internal sealed class SessionService : BaseService<SysUser>, ISessionService
var r = items.Select((it) =>
{
var reuslt = it.Adapt<SessionOutput>();
var reuslt = it.AdaptSessionOutput();
if (verificatInfoDicts.TryGetValue(it.Id, out var verificatInfos))
{
reuslt.VerificatCount = verificatInfos.Count;//令牌数量
@@ -117,7 +115,7 @@ internal sealed class SessionService : BaseService<SysUser>, ISessionService
var r = items.Select((it) =>
{
var reuslt = it.Adapt<SessionOutput>();
var reuslt = it.AdaptSessionOutput();
if (verificatInfoDicts.TryGetValue(it.Id, out var verificatInfos))
{
reuslt.VerificatCount = verificatInfos.Count;//令牌数量

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using ThingsGateway.DataEncryption;
using ThingsGateway.Extension;
using ThingsGateway.Extension.Generic;
@@ -452,7 +450,7 @@ internal sealed class SysUserService : BaseService<SysUser>, ISysUserService
if (changedType == ItemChangedType.Add)
{
var sysUser = input.Adapt<SysUser>();
var sysUser = input.AdaptSysUser();
//获取默认密码
sysUser.Avatar = input.Avatar;
sysUser.Password = await GetDefaultPassWord(true).ConfigureAwait(false);//设置密码
@@ -872,7 +870,7 @@ internal sealed class SysUserService : BaseService<SysUser>, ISysUserService
sysUser.OrgAndPosIdList.AddRange(sysUser.OrgId, sysUser.PositionId ?? 0);//添加组织和职位Id
if (sysUser.DirectorId != null)
{
sysUser.DirectorInfo = (await GetUserByIdAsync(sysUser.DirectorId.Value).ConfigureAwait(false)).Adapt<UserSelectorOutput>();//获取主管信息
sysUser.DirectorInfo = (await GetUserByIdAsync(sysUser.DirectorId.Value).ConfigureAwait(false)).AdaptUserSelectorOutput();//获取主管信息
}
//获取按钮码

View File

@@ -18,6 +18,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Riok.Mapperly" Version="4.2.1" ExcludeAssets="runtime" PrivateAssets="all" />
<PackageReference Include="Rougamo.Fody" Version="5.0.1" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using ThingsGateway.Admin.Application;
using ThingsGateway.NewLife;
using ThingsGateway.NewLife.Extension;
@@ -88,7 +86,7 @@ public class BlazorAppContext
if (UserManager.UserId > 0)
{
url = url.StartsWith('/') ? url : $"/{url}";
var sysResources = (await ResourceService.GetAllAsync()).Adapt<List<SysResource>>();
var sysResources = (await ResourceService.GetAllAsync()).AdaptListSysResource();
if (TitleLocalizer != null)
{
sysResources.ForEach(a =>
@@ -121,7 +119,7 @@ public class BlazorAppContext
CurrentModuleId = moduleId.Value;
}
UserWorkBench = await UserCenterService.GetLoginWorkbenchAsync(UserManager.UserId);
OwnMenus = (await UserCenterService.GetOwnMenuAsync(UserManager.UserId, 0)).Adapt<List<SysResource>>();
OwnMenus = (await UserCenterService.GetOwnMenuAsync(UserManager.UserId, 0)).AdaptListSysResource();
if (TitleLocalizer != null)
{

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using ThingsGateway.Admin.Application;
@@ -30,7 +28,7 @@ public partial class AppConfigPage
protected override async Task OnParametersSetAsync()
{
AppConfig = (await SysDictService.GetAppConfigAsync()).Adapt<AppConfig>();
AppConfig = (await SysDictService.GetAppConfigAsync()).AdaptAppConfig();
await base.OnParametersSetAsync();
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using ThingsGateway.Admin.Application;
namespace ThingsGateway.Admin.Razor;
@@ -47,10 +45,7 @@ public partial class RoleChoiceDialog
private ISysRoleService? SysRoleService { get; set; }
private async Task<QueryData<SysRole>> OnQueryAsync(QueryPageOptions options)
{
var data = await SysRoleService.PageAsync(options, a => a.Where(b => b.OrgId == OrgId));
QueryData<SysRole> queryData = data.Adapt<QueryData<SysRole>>();
return queryData;
return await SysRoleService.PageAsync(options, a => a.Where(b => b.OrgId == OrgId));
}
#region
private long OrgId { get; set; }

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using ThingsGateway.Admin.Application;
namespace ThingsGateway.Admin.Razor;
@@ -56,7 +54,7 @@ public partial class UserChoiceDialog
OrgId = OrgId,
PositionId = PositionId,
});
QueryData<UserSelectorOutput> queryData = data.Adapt<QueryData<UserSelectorOutput>>();
QueryData<UserSelectorOutput> queryData = data.AdaptQueryDataUserSelectorOutput();
return queryData;
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using ThingsGateway.Admin.Application;
@@ -37,9 +35,9 @@ public partial class UserCenterPage
protected override async Task OnParametersSetAsync()
{
SysUser = AppContext.CurrentUser.Adapt<SysUser>();
SysUser = AppContext.CurrentUser.AdaptSysUser();
SysUser.Avatar = AppContext.Avatar;
WorkbenchInfo = (await UserCenterService.GetLoginWorkbenchAsync(SysUser.Id)).Adapt<WorkbenchInfo>();
WorkbenchInfo = (await UserCenterService.GetLoginWorkbenchAsync(SysUser.Id)).AdaptWorkbenchInfo();
await base.OnParametersSetAsync();
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using ThingsGateway.Admin.Application;
namespace ThingsGateway.Admin.Razor;
@@ -122,31 +120,4 @@ public static class ResourceUtil
return trees;
}
/// <summary>
/// 构建树节点
/// </summary>
public static List<TreeViewItem<T>> BuildTreeItemList<T>(IEnumerable<SysResource> sysresources, List<long> selectedItems, Microsoft.AspNetCore.Components.RenderFragment<T> render, long parentId = 0, TreeViewItem<T>? parent = null, Func<SysResource, bool> disableFunc = null) where T : class
{
if (sysresources == null) return null;
var trees = new List<TreeViewItem<T>>();
var roots = sysresources.Where(i => i.ParentId == parentId).OrderBy(i => i.SortCode);
foreach (var node in roots)
{
var item = new TreeViewItem<T>(node.Adapt<T>())
{
Text = node.Title,
Icon = node.Icon,
IsDisabled = disableFunc == null ? false : disableFunc(node),
IsActive = selectedItems.Any(v => node.Id == v),
IsExpand = true,
Parent = parent,
Template = render,
CheckedState = selectedItems.Any(i => i == node.Id) ? CheckboxState.Checked : CheckboxState.UnChecked
};
item.Items = BuildTreeItemList(sysresources, selectedItems, render, node.Id, item, disableFunc) ?? new();
trees.Add(item);
}
return trees;
}
}

View File

@@ -11,8 +11,6 @@
#pragma warning disable CA2007 // 考虑对等待的任务调用 ConfigureAwait
using BootstrapBlazor.Components;
using Mapster;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.Extensions.Localization;
@@ -71,7 +69,7 @@ public partial class Login
private async Task LoginAsync(EditContext context)
{
var model = loginModel.Adapt<LoginInput>();
var model = loginModel.AdaptLoginInput();
model.Password = DESEncryption.Encrypt(model.Password);
try
{

View File

@@ -11,8 +11,6 @@
using BootstrapBlazor.Components;
using Mapster;
using MiniExcelLibs;
using MiniExcelLibs.Attributes;
using MiniExcelLibs.OpenXml;

View File

@@ -210,7 +210,7 @@ public static class AppServiceCollectionExtensions
services.AddStartups();
// 添加对象映射
services.AddObjectMapper();
//services.AddObjectMapper();
// 默认内置 GBKWindows-1252, Shift-JIS, GB2312 编码支持
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

View File

@@ -1,59 +1,59 @@
// ------------------------------------------------------------------------
// 版权信息
// 版权归百小僧及百签科技(广东)有限公司所有。
// 所有权利保留。
// 官方网站https://baiqian.com
//
// 许可证信息
// 项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// ------------------------------------------------------------------------
//// ------------------------------------------------------------------------
//// 版权信息
//// 版权归百小僧及百签科技(广东)有限公司所有。
//// 所有权利保留。
//// 官方网站https://baiqian.com
////
//// 许可证信息
//// 项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。
//// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
//// ------------------------------------------------------------------------
using Mapster;
//using Mapster;
using System.Reflection;
//using System.Reflection;
using ThingsGateway;
//using ThingsGateway;
namespace Microsoft.Extensions.DependencyInjection;
//namespace Microsoft.Extensions.DependencyInjection;
/// <summary>
/// 对象映射拓展类
/// </summary>
[SuppressSniffer]
public static class ObjectMapperServiceCollectionExtensions
{
///// <summary>
///// 对象映射拓展类
///// </summary>
//[SuppressSniffer]
//public static class ObjectMapperServiceCollectionExtensions
//{
/// <summary>
/// 添加对象映射
/// </summary>
/// <param name="services">服务集合</param>
/// <returns></returns>
public static IServiceCollection AddObjectMapper(this IServiceCollection services)
{
// 判断是否安装了 Mapster 程序集
return services.AddObjectMapper(App.Assemblies.ToArray());
}
// /// <summary>
// /// 添加对象映射
// /// </summary>
// /// <param name="services">服务集合</param>
// /// <returns></returns>
// public static IServiceCollection AddObjectMapper(this IServiceCollection services)
// {
// // 判断是否安装了 Mapster 程序集
// return services.AddObjectMapper(App.Assemblies.ToArray());
// }
/// <summary>
/// 添加对象映射
/// </summary>
/// <param name="services">服务集合</param>
/// <param name="assemblies">扫描的程序集</param>
/// <returns></returns>
public static IServiceCollection AddObjectMapper(this IServiceCollection services, params Assembly[] assemblies)
{
// 获取全局映射配置
var config = TypeAdapterConfig.GlobalSettings;
// /// <summary>
// /// 添加对象映射
// /// </summary>
// /// <param name="services">服务集合</param>
// /// <param name="assemblies">扫描的程序集</param>
// /// <returns></returns>
// public static IServiceCollection AddObjectMapper(this IServiceCollection services, params Assembly[] assemblies)
// {
// // 获取全局映射配置
// var config = TypeAdapterConfig.GlobalSettings;
//config.Compiler = exp => exp.CompileFast();
// //config.Compiler = exp => exp.CompileFast();
// 扫描所有继承 IRegister 接口的对象映射配置
if (assemblies?.Length > 0) config.Scan(assemblies);
// // 扫描所有继承 IRegister 接口的对象映射配置
// if (assemblies?.Length > 0) config.Scan(assemblies);
// 配置支持依赖注入
services.AddSingleton(config);
// // 配置支持依赖注入
// services.AddSingleton(config);
return services;
}
}
// return services;
// }
//}

View File

@@ -36,7 +36,7 @@
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
<!--<PackageReference Include="FastExpressionCompiler" Version="5.3.0" />-->
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageReference Include="Mapster" Version="7.4.0" />
<!--<PackageReference Include="Mapster" Version="7.4.0" />-->
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.5.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.1" />
</ItemGroup>

View File

@@ -1,30 +1,30 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
//------------------------------------------------------------------------------
////------------------------------------------------------------------------------
//// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
//// 此代码版权除特别声明外的代码归作者本人Diego所有
//// 源代码使用协议遵循本仓库的开源协议及附加协议
//// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
//// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
//// 使用文档https://thingsgateway.cn/
//// QQ群605534569
////------------------------------------------------------------------------------
using Mapster;
//using Mapster;
using System.Text;
//using System.Text;
namespace ThingsGateway.Razor;
//namespace ThingsGateway.Razor;
/// <summary>
/// <see cref="Encoding"/> Master规则
/// </summary>
public class EncodingMapper : IRegister
{
/// <inheritdoc/>
public void Register(TypeAdapterConfig config)
{
config.ForType<Encoding, Encoding>()
.Ignore(dest => dest.EncoderFallback)
.Ignore(dest => dest.DecoderFallback)
.ConstructUsing(src => Encoding.GetEncoding(src.CodePage));
}
}
///// <summary>
///// <see cref="Encoding"/> Master规则
///// </summary>
//public class EncodingMapper : IRegister
//{
// /// <inheritdoc/>
// public void Register(TypeAdapterConfig config)
// {
// config.ForType<Encoding, Encoding>()
// .Ignore(dest => dest.EncoderFallback)
// .Ignore(dest => dest.DecoderFallback)
// .ConstructUsing(src => Encoding.GetEncoding(src.CodePage));
// }
//}

View File

@@ -35,7 +35,10 @@
</ItemGroup>-->
<ItemGroup>
<ProjectReference Include="..\BlazorSetParametersAsyncGenerator\BlazorSetParametersAsyncGenerator.csproj" PrivateAssets="all" OutputItemType="Analyzer" />
<ProjectReference Include="..\BlazorSetParametersAsyncGenerator\BlazorSetParametersAsyncGenerator.csproj" PrivateAssets="all" OutputItemType="Analyzer">
<ExcludeAssets>all</ExcludeAssets>
<IncludeAssets>Analyzer</IncludeAssets>
</ProjectReference>
</ItemGroup>
</Project>

View File

@@ -1,10 +1,10 @@
<Project>
<PropertyGroup>
<PluginVersion>10.9.3</PluginVersion>
<ProPluginVersion>10.9.3</ProPluginVersion>
<AuthenticationVersion>2.9.1</AuthenticationVersion>
<SourceGeneratorVersion>10.9.3</SourceGeneratorVersion>
<PluginVersion>10.9.4</PluginVersion>
<ProPluginVersion>10.9.4</ProPluginVersion>
<AuthenticationVersion>2.9.4</AuthenticationVersion>
<SourceGeneratorVersion>10.9.4</SourceGeneratorVersion>
<NET8Version>8.0.17</NET8Version>
<NET9Version>9.0.6</NET9Version>
<SatelliteResourceLanguages>zh-Hans;en-US</SatelliteResourceLanguages>

View File

@@ -104,7 +104,7 @@ internal sealed class VariableCodeBuilder
private void BuildMethod(StringBuilder stringBuilder, IPropertySymbol propertySymbol)
{
var attributeData = propertySymbol.GetAttributes().FirstOrDefault(a => a.AttributeClass.ToDisplayString() == VariableSyntaxReceiver.VariableRuntimeAttributeTypeName);
var attributeData = propertySymbol.GetAttributes().FirstOrDefault(a => a.AttributeClass.ToDisplayString() == VariableObjectSyntaxFilter.VariableRuntimeAttributeTypeName);
stringBuilder.AppendLine();
stringBuilder.AppendLine($"public ValueTask<OperResult> Write{propertySymbol.Name}Async({propertySymbol.Type} value,CancellationToken cancellationToken=default)");
stringBuilder.AppendLine("{");
@@ -120,7 +120,7 @@ internal sealed class VariableCodeBuilder
.OfType<IPropertySymbol>()
.Where(m =>
{
return m.GetAttributes().Any(a => a.AttributeClass.ToDisplayString() == VariableSyntaxReceiver.VariableRuntimeAttributeTypeName);
return m.GetAttributes().Any(a => a.AttributeClass.ToDisplayString() == VariableObjectSyntaxFilter.VariableRuntimeAttributeTypeName);
});
}
}

View File

@@ -8,32 +8,23 @@
// QQ群605534569
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页http://rrqm_home.gitee.io/touchsocket/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
#if !NET45_OR_GREATER
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
using System.Text;
namespace ThingsGateway.Foundation;
/// <summary>
/// 源生成
/// 增量源生成VariableObject
/// </summary>
[Generator]
public class VariableObjectSourceGenerator : ISourceGenerator
public sealed class VariableObjectSourceGenerator : IIncrementalGenerator
{
private string m_generatorVariableAttribute = @"
private const string AttributeSource = @"
using System;
namespace ThingsGateway.Foundation
@@ -42,47 +33,49 @@ namespace ThingsGateway.Foundation
/// 使用源生成变量写入方法的调用。
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
internal class GeneratorVariableAttribute:Attribute
internal class GeneratorVariableAttribute : Attribute
{
}
}
";
/// <inheritdoc/>
public void Initialize(GeneratorInitializationContext context)
public void Initialize(IncrementalGeneratorInitializationContext context)
{
//Debugger.Launch();
context.RegisterForPostInitialization(a =>
context.RegisterPostInitializationOutput(ctx =>
{
a.AddSource(nameof(m_generatorVariableAttribute), m_generatorVariableAttribute);
ctx.AddSource("GeneratorVariableAttribute.g.cs", SourceText.From(AttributeSource, Encoding.UTF8));
});
context.RegisterForSyntaxNotifications(() => new VariableSyntaxReceiver());
}
/// <inheritdoc/>
public void Execute(GeneratorExecutionContext context)
{
var s = context.Compilation.GetMetadataReference(context.Compilation.Assembly);
var variableObjectTypes = context.SyntaxProvider
.CreateSyntaxProvider(
predicate: VariableObjectSyntaxFilter.IsCandidate,
transform: VariableObjectSyntaxFilter.GetVariableObjectType)
.Where(static t => t is not null)
.Select(static (t, _) => (INamedTypeSymbol)t!) // 明确转成 INamedTypeSymbol
.Collect();
if (context.SyntaxReceiver is VariableSyntaxReceiver receiver)
var compilationAndTypes = context.CompilationProvider.Combine(variableObjectTypes);
context.RegisterSourceOutput(compilationAndTypes, (spc, source) =>
{
var builders = receiver
.GetVariableObjectTypes(context.Compilation)
.Select(i => new VariableCodeBuilder(i))
.Distinct();
foreach (var builder in builders)
var (compilation, types) = source;
foreach (var typeSymbol in types.ToList().Distinct(SymbolEqualityComparer.Default).OfType<INamedTypeSymbol>())
{
var builder = new VariableCodeBuilder(typeSymbol);
if (builder.TryToSourceText(out var sourceText))
{
var tree = CSharpSyntaxTree.ParseText(sourceText);
var root = tree.GetRoot().NormalizeWhitespace();
var ret = root.ToFullString();
context.AddSource($"{builder.GetFileName()}.g.cs", ret);
spc.AddSource($"{builder.GetFileName()}.g.cs", SourceText.From(ret, Encoding.UTF8));
}
}
}
});
}
}
#endif

View File

@@ -0,0 +1,52 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
internal static class VariableObjectSyntaxFilter
{
public const string GeneratorVariableAttributeTypeName = "ThingsGateway.Foundation.GeneratorVariableAttribute";
public const string VariableRuntimeAttributeTypeName = "ThingsGateway.Foundation.VariableRuntimeAttribute";
/// <summary>
/// 语法筛选器:只筛选 ClassDeclarationSyntax
/// </summary>
public static bool IsCandidate(SyntaxNode syntaxNode, CancellationToken _)
{
return syntaxNode is ClassDeclarationSyntax;
}
/// <summary>
/// 语义分析:判断是否是带 GeneratorVariableAttribute 的类
/// </summary>
public static INamedTypeSymbol? GetVariableObjectType(GeneratorSyntaxContext context, CancellationToken _)
{
var classSyntax = (ClassDeclarationSyntax)context.Node;
var classSymbol = context.SemanticModel.GetDeclaredSymbol(classSyntax) as INamedTypeSymbol;
if (classSymbol == null)
return null;
if (classSymbol.IsAbstract)
return null;
var generatorAttr = context.SemanticModel.Compilation.GetTypeByMetadataName(GeneratorVariableAttributeTypeName);
if (generatorAttr == null)
return null;
if (HasAttribute(classSymbol, generatorAttr))
return classSymbol;
return null;
}
/// <summary>
/// 判断 symbol 是否声明了指定 Attribute
/// </summary>
public static bool HasAttribute(INamedTypeSymbol symbol, INamedTypeSymbol attributeSymbol)
{
foreach (var attr in symbol.GetAttributes())
{
if (SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeSymbol))
return true;
}
return false;
}
}

View File

@@ -1,116 +0,0 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在XREF结尾的命名空间的代码归作者本人若汝棋茗所有
// 源代码使用协议遵循本仓库的开源协议及附加协议若本仓库没有设置则按MIT开源协议授权
// CSDN博客https://blog.csdn.net/qq_40374647
// 哔哩哔哩视频https://space.bilibili.com/94253567
// Gitee源代码仓库https://gitee.com/RRQM_Home
// Github源代码仓库https://github.com/RRQM
// API首页http://rrqm_home.gitee.io/touchsocket/
// 交流QQ群234762506
// 感谢您的下载和使用
//------------------------------------------------------------------------------
#if !NET45_OR_GREATER
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace ThingsGateway.Foundation;
internal sealed class VariableSyntaxReceiver : ISyntaxReceiver
{
public const string GeneratorVariableAttributeTypeName = "ThingsGateway.Foundation.GeneratorVariableAttribute";
public const string VariableRuntimeAttributeTypeName = "ThingsGateway.Foundation.VariableRuntimeAttribute";
/// <summary>
/// 接口列表
/// </summary>
private readonly List<ClassDeclarationSyntax> m_classSyntaxList = new List<ClassDeclarationSyntax>();
/// <summary>
/// 访问语法树
/// </summary>
/// <param name="syntaxNode"></param>
void ISyntaxReceiver.OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
if (syntaxNode is ClassDeclarationSyntax syntax)
{
m_classSyntaxList.Add(syntax);
}
}
public INamedTypeSymbol GeneratorVariableAttributeAttribute { get; private set; }
/// <summary>
/// 获取所有插件符号
/// </summary>
/// <param name="compilation"></param>
/// <returns></returns>
public IEnumerable<INamedTypeSymbol> GetVariableObjectTypes(Compilation compilation)
{
GeneratorVariableAttributeAttribute = compilation.GetTypeByMetadataName(GeneratorVariableAttributeTypeName)!;
if (GeneratorVariableAttributeAttribute == null)
{
yield break;
}
foreach (var classSyntax in m_classSyntaxList)
{
var @class = compilation.GetSemanticModel(classSyntax.SyntaxTree).GetDeclaredSymbol(classSyntax);
if (@class != null && IsVariableObject(@class))
{
yield return @class;
}
}
}
/// <summary>
/// 是否为变量类
/// </summary>
/// <param name="class"></param>
/// <returns></returns>
public bool IsVariableObject(INamedTypeSymbol @class)
{
if (GeneratorVariableAttributeAttribute is null)
{
return false;
}
if (@class.IsAbstract)
{
return false;
}
return HasAttribute(@class, GeneratorVariableAttributeAttribute);
}
/// <summary>
/// 返回是否声明指定的特性
/// </summary>
/// <param name="symbol"></param>
/// <param name="attribute"></param>
/// <returns></returns>
public static bool HasAttribute(ISymbol symbol, INamedTypeSymbol attribute)
{
foreach (var attr in symbol.GetAttributes())
{
var attrClass = attr.AttributeClass;
if (attrClass != null && (attrClass.AllInterfaces.Contains(attribute) || SymbolEqualityComparer.Default.Equals(attrClass, attribute)))
{
return true;
}
}
return false;
}
}
#endif

View File

@@ -8,6 +8,6 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" PrivateAssets="all" />
</ItemGroup>
</Project>

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -153,7 +151,7 @@ public class ControlController : ControllerBase
[DisplayName("保存通道")]
public Task<bool> BatchSaveChannelAsync([FromBody] List<ChannelInput> channels, ItemChangedType type, bool restart)
{
return GlobalData.ChannelRuntimeService.BatchSaveChannelAsync(channels.Adapt<List<Channel>>(), type, restart);
return GlobalData.ChannelRuntimeService.BatchSaveChannelAsync(channels.AdaptListChannel(), type, restart);
}
/// <summary>
@@ -163,7 +161,7 @@ public class ControlController : ControllerBase
[DisplayName("保存设备")]
public Task<bool> BatchSaveDeviceAsync([FromBody] List<DeviceInput> devices, ItemChangedType type, bool restart)
{
return GlobalData.DeviceRuntimeService.BatchSaveDeviceAsync(devices.Adapt<List<Device>>(), type, restart);
return GlobalData.DeviceRuntimeService.BatchSaveDeviceAsync(devices.AdaptListDevice(), type, restart);
}
/// <summary>
@@ -173,7 +171,7 @@ public class ControlController : ControllerBase
[DisplayName("保存变量")]
public Task<bool> BatchSaveVariableAsync([FromBody] List<VariableInput> variables, ItemChangedType type, bool restart)
{
return GlobalData.VariableRuntimeService.BatchSaveVariableAsync(variables.Adapt<List<Variable>>(), type, restart, default);
return GlobalData.VariableRuntimeService.BatchSaveVariableAsync(variables.AdaptListVariable(), type, restart, default);
}
/// <summary>

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using ThingsGateway.Extension.Generic;
using TouchSocket.Core;
@@ -79,12 +77,12 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
CollectDevices?.ForEach(a =>
{
if (a.Value.DeviceStatus == DeviceStatusEnum.OnLine && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
DeviceStatusChange(a.Value, a.Value.Adapt<DeviceBasicData>());
DeviceStatusChange(a.Value, a.Value.AdaptDeviceBasicData());
});
IdVariableRuntimes.ForEach(a =>
{
if (a.Value.IsOnline && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
VariableValueChange(a.Value, a.Value.AdaptVariableBasicData());
});
}
@@ -153,7 +151,7 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
LogMessage?.LogDebug($"Interval {typeof(VarModel).Name} data, count {IdVariableRuntimes.Count}");
// 间隔推送全部变量
var variableRuntimes = IdVariableRuntimes.Select(a => a.Value);
VariableTimeInterval(variableRuntimes, variableRuntimes.Adapt<List<VariableBasicData>>());
VariableTimeInterval(variableRuntimes, variableRuntimes.AdaptIEnumerableVariableBasicData());
}
catch (Exception ex)
{
@@ -169,7 +167,7 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
// 间隔推送全部设备
foreach (var deviceRuntime in CollectDevices.Select(a => a.Value))
{
DeviceTimeInterval(deviceRuntime, deviceRuntime.Adapt<DeviceBasicData>());
DeviceTimeInterval(deviceRuntime, deviceRuntime.AdaptDeviceBasicData());
}
}
}
@@ -202,7 +200,7 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
/// </summary>
/// <param name="variableRuntimes">变量运行时信息</param>
/// <param name="variables">变量数据</param>
protected virtual void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, List<VariableBasicData> variables)
protected virtual void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, IEnumerable<VariableBasicData> variables)
{
// 在变量状态变化时执行的自定义逻辑
}
@@ -237,12 +235,12 @@ public abstract class BusinessBaseWithCacheIntervalAlarmModel<VarModel, DevModel
CollectDevices?.ForEach(a =>
{
if (a.Value.DeviceStatus == DeviceStatusEnum.OnLine && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
DeviceStatusChange(a.Value, a.Value.Adapt<DeviceBasicData>());
DeviceStatusChange(a.Value, a.Value.AdaptDeviceBasicData());
});
IdVariableRuntimes.ForEach(a =>
{
if (a.Value.IsOnline && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
VariableValueChange(a.Value, a.Value.AdaptVariableBasicData());
});
}
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using ThingsGateway.Extension.Generic;
using TouchSocket.Core;
@@ -69,12 +67,12 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
CollectDevices?.ForEach(a =>
{
if (a.Value.DeviceStatus == DeviceStatusEnum.OnLine && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
DeviceStatusChange(a.Value, a.Value.Adapt<DeviceBasicData>());
DeviceStatusChange(a.Value, a.Value.AdaptDeviceBasicData());
});
IdVariableRuntimes.ForEach(a =>
{
if (a.Value.IsOnline && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
VariableValueChange(a.Value, a.Value.AdaptVariableBasicData());
});
}
@@ -133,7 +131,7 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
LogMessage?.LogDebug($"Interval {typeof(VarModel).Name} data, count {IdVariableRuntimes.Count}");
// 上传所有变量信息
var variableRuntimes = IdVariableRuntimes.Select(a => a.Value);
VariableTimeInterval(variableRuntimes, variableRuntimes.Adapt<List<VariableBasicData>>());
VariableTimeInterval(variableRuntimes, variableRuntimes.AdaptIEnumerableVariableBasicData());
}
catch (Exception ex)
{
@@ -148,7 +146,7 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
// 上传所有设备信息
foreach (var deviceRuntime in CollectDevices.Select(a => a.Value))
{
DeviceTimeInterval(deviceRuntime, deviceRuntime.Adapt<DeviceBasicData>());
DeviceTimeInterval(deviceRuntime, deviceRuntime.AdaptDeviceBasicData());
}
}
}
@@ -179,7 +177,7 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
/// </summary>
/// <param name="variableRuntimes">变量运行时信息</param>
/// <param name="variables">变量数据</param>
protected virtual void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, List<VariableBasicData> variables)
protected virtual void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, IEnumerable<VariableBasicData> variables)
{
// 在变量状态变化时执行的自定义逻辑
}
@@ -234,12 +232,12 @@ public abstract class BusinessBaseWithCacheIntervalDeviceModel<VarModel, DevMode
CollectDevices?.ForEach(a =>
{
if (a.Value.DeviceStatus == DeviceStatusEnum.OnLine && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
DeviceStatusChange(a.Value, a.Value.Adapt<DeviceBasicData>());
DeviceStatusChange(a.Value, a.Value.AdaptDeviceBasicData());
});
IdVariableRuntimes.ForEach(a =>
{
if (a.Value.IsOnline && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
VariableValueChange(a.Value, a.Value.AdaptVariableBasicData());
});
}
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using ThingsGateway.Extension.Generic;
using TouchSocket.Core;
@@ -65,7 +63,7 @@ public abstract class BusinessBaseWithCacheIntervalVariableModel<VarModel> : Bus
IdVariableRuntimes.ForEach(a =>
{
if (a.Value.IsOnline && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
VariableValueChange(a.Value, a.Value.AdaptVariableBasicData());
});
}
@@ -100,7 +98,7 @@ public abstract class BusinessBaseWithCacheIntervalVariableModel<VarModel> : Bus
LogMessage?.LogDebug($"Interval {typeof(VarModel).Name} data, count {IdVariableRuntimes.Count}");
// 上传所有变量信息
var variableRuntimes = IdVariableRuntimes.Select(a => a.Value);
VariableTimeInterval(variableRuntimes, variableRuntimes.Adapt<List<VariableBasicData>>());
VariableTimeInterval(variableRuntimes, variableRuntimes.AdaptIEnumerableVariableBasicData());
}
catch (Exception ex)
{
@@ -131,7 +129,7 @@ public abstract class BusinessBaseWithCacheIntervalVariableModel<VarModel> : Bus
/// </summary>
/// <param name="variableRuntimes">变量运行时信息</param>
/// <param name="variables">变量数据</param>
protected virtual void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, List<VariableBasicData> variables)
protected virtual void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, IEnumerable<VariableBasicData> variables)
{
// 在变量状态变化时执行的自定义逻辑
}
@@ -162,7 +160,7 @@ public abstract class BusinessBaseWithCacheIntervalVariableModel<VarModel> : Bus
IdVariableRuntimes.ForEach(a =>
{
if (a.Value.IsOnline && _businessPropertyWithCacheInterval.BusinessUpdateEnum != BusinessUpdateEnum.Interval)
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
VariableValueChange(a.Value, a.Value.AdaptVariableBasicData());
});
}
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
@@ -668,7 +666,20 @@ public abstract class CollectBase : DriverBase, IRpcDriver
{
// 调用方法并获取结果
var data = await variableMethod.InvokeMethodAsync(this, value, cancellationToken).ConfigureAwait(false);
result = data.Adapt<OperResult<object>>();
result = new(data);
var operResultType = typeof(IOperResult<>);
var interfaceType = data.GetType().GetInterfaces()
.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == operResultType);
if (interfaceType != null)
{
var contentProperty = interfaceType.GetProperty("Content");
if (contentProperty != null)
{
result.Content = contentProperty.GetValue(data);
}
}
// 如果方法有返回值,并且是读取操作
if (method.HasReturn && isRead)

View File

@@ -10,7 +10,7 @@
using BootstrapBlazor.Components;
using Mapster;
using Riok.Mapperly.Abstractions;
using System.ComponentModel.DataAnnotations;
@@ -183,7 +183,7 @@ public class Device : BaseDataEntity, IValidatableObject
/// </summary>
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
public ModelValueValidateForm? ModelValueValidateForm;
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{

View File

@@ -10,7 +10,7 @@
using BootstrapBlazor.Components;
using Mapster;
using Riok.Mapperly.Abstractions;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
@@ -107,7 +107,7 @@ public class Variable : BaseDataEntity, IValidatableObject
/// </summary>
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
public ConcurrentDictionary<long, ModelValueValidateForm>? VariablePropertyModels;

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using System.Collections.Concurrent;
using ThingsGateway.Extension.Generic;
@@ -498,7 +496,7 @@ public static class GlobalData
// 触发设备状态变化事件,并将设备运行时对象转换为设备数据对象进行传递
DeviceStatusChangeEvent?.Invoke(deviceRuntime, deviceRuntime.Adapt<DeviceBasicData>());
DeviceStatusChangeEvent?.Invoke(deviceRuntime, deviceRuntime.AdaptDeviceBasicData());
}
@@ -511,7 +509,7 @@ public static class GlobalData
// 触发变量值变化事件,并将变量运行时对象转换为变量数据对象进行传递
VariableValueChangeEvent?.Invoke(variableRuntime, variableRuntime.Adapt<VariableBasicData>());
VariableValueChangeEvent?.Invoke(variableRuntime, variableRuntime.AdaptVariableBasicData());
}
/// <summary>

View File

@@ -0,0 +1,62 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
//------------------------------------------------------------------------------
using Riok.Mapperly.Abstractions;
using ThingsGateway.Management;
namespace ThingsGateway.Gateway.Application;
[Mapper(UseDeepCloning = true, EnumMappingStrategy = EnumMappingStrategy.ByName, RequiredMappingStrategy = RequiredMappingStrategy.None)]
public static partial class GatewayMapper
{
public static partial AlarmVariable AdaptAlarmVariable(this VariableRuntime src);
public static partial DeviceBasicData AdaptDeviceBasicData(this DeviceRuntime src);
public static partial IEnumerable<DeviceBasicData> AdaptIEnumerableDeviceBasicData(this IEnumerable<DeviceRuntime> src);
public static partial List<DeviceBasicData> AdaptListDeviceBasicData(this IEnumerable<DeviceRuntime> src);
public static partial VariableBasicData AdaptVariableBasicData(this VariableRuntime src);
public static partial IEnumerable<VariableBasicData> AdaptIEnumerableVariableBasicData(this IEnumerable<VariableRuntime> src);
public static partial List<VariableBasicData> AdaptListVariableBasicData(this IEnumerable<VariableRuntime> src);
public static partial Variable AdaptVariable(this VariableRuntime src);
[MapProperty(nameof(Variable.InitValue), nameof(VariableRuntime.Value))]
public static partial VariableRuntime AdaptVariableRuntime(this Variable src);
public static partial List<Variable> AdaptListVariable(this IEnumerable<Variable> src);
public static partial DeviceRuntime AdaptDeviceRuntime(this Device src);
public static partial ChannelRuntime AdaptChannelRuntime(this Channel src);
public static partial List<VariableRuntime> AdaptListVariableRuntime(this IEnumerable<Variable> src);
public static partial List<DeviceRuntime> AdaptListDeviceRuntime(this IEnumerable<Device> src);
public static partial List<Device> AdaptListDevice(this IEnumerable<Device> src);
public static partial List<ChannelRuntime> AdaptListChannelRuntime(this IEnumerable<Channel> src);
public static partial List<Channel> AdaptListChannel(this IEnumerable<Channel> src);
public static partial List<Variable> AdaptListVariable(this IEnumerable<VariableRuntime> src);
public static partial List<DeviceDataWithValue> AdaptDeviceDataWithValue(this IEnumerable<DeviceRuntime> src);
public static partial RedundancyOptions AdaptRedundancyOptions(this RedundancyOptions src);
public static partial List<DeviceDataWithValue> AdaptListDeviceDataWithValue(this IEnumerable<DeviceRuntime> src);
public static partial List<Channel> AdaptListChannel(this List<ChannelInput> src);
public static partial List<Device> AdaptListDevice(this List<DeviceInput> src);
public static partial List<Variable> AdaptListVariable(this List<VariableInput> src);
public static partial Channel AdaptChannel(this Channel src);
public static partial Device AdaptDevice(this Device src);
public static partial Variable AdaptVariable(this Variable src);
public static partial List<PluginInfo> AdaptListPluginInfo(this List<PluginInfo> src);
public static partial List<VariableBasicData> AdaptIEnumerableVariableBasicData(this IGrouping<string, VariableBasicData> src);
}

View File

@@ -10,7 +10,7 @@
using BootstrapBlazor.Components;
using Mapster;
using Riok.Mapperly.Abstractions;
using System.Collections.Concurrent;
@@ -30,7 +30,7 @@ public class ChannelRuntime : Channel, IChannelOptions, IDisposable
/// </summary>
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
public PluginInfo? PluginInfo { get; set; }
@@ -47,7 +47,7 @@ public class ChannelRuntime : Channel, IChannelOptions, IDisposable
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
public WaitLock WaitLock { get; private set; } = new WaitLock();
@@ -79,13 +79,13 @@ public class ChannelRuntime : Channel, IChannelOptions, IDisposable
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
public TouchSocketConfig Config { get; set; } = new();
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
public IReadOnlyDictionary<long, DeviceRuntime>? ReadDeviceRuntimes => DeviceRuntimes;
@@ -94,7 +94,7 @@ public class ChannelRuntime : Channel, IChannelOptions, IDisposable
/// </summary>
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
internal ConcurrentDictionary<long, DeviceRuntime>? DeviceRuntimes { get; } = new(Environment.ProcessorCount, 1000);
@@ -107,7 +107,7 @@ public class ChannelRuntime : Channel, IChannelOptions, IDisposable
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
public IDeviceThreadManage? DeviceThreadManage { get; internal set; }

View File

@@ -19,15 +19,12 @@ namespace ThingsGateway.Gateway.Application;
/// </summary>
public class DeviceBasicData
{
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public DeviceRuntime DeviceRuntime { get; set; }
/// <inheritdoc cref="PrimaryIdEntity.Id"/>
public long Id { get; set; }
/// <inheritdoc cref="Device.Name"/>
public string Name => DeviceRuntime?.Name;
public string Name { get; set; }
/// <inheritdoc cref="DeviceRuntime.ActiveTime"/>
public DateTime ActiveTime { get; set; }
@@ -41,37 +38,37 @@ public class DeviceBasicData
public string LastErrorMessage { get; set; }
/// <inheritdoc cref="DeviceRuntime.PluginName"/>
public string PluginName => DeviceRuntime?.PluginName;
public string PluginName { get; set; }
/// <inheritdoc cref="Device.Description"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string? Description => DeviceRuntime?.Description;
public string? Description { get; set; }
/// <inheritdoc cref="Device.Remark1"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string Remark1 => DeviceRuntime?.Remark1;
public string Remark1 { get; set; }
/// <inheritdoc cref="Device.Remark2"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string Remark2 => DeviceRuntime?.Remark2;
public string Remark2 { get; set; }
/// <inheritdoc cref="Device.Remark3"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string Remark3 => DeviceRuntime?.Remark3;
public string Remark3 { get; set; }
/// <inheritdoc cref="Device.Remark4"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string Remark4 => DeviceRuntime?.Remark4;
public string Remark4 { get; set; }
/// <inheritdoc cref="Device.Remark5"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string Remark5 => DeviceRuntime?.Remark5;
public string Remark5 { get; set; }
}
@@ -81,31 +78,28 @@ public class DeviceBasicData
/// </summary>
public class VariableBasicData
{
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
public VariableRuntime VariableRuntime { get; set; }
/// <inheritdoc cref="PrimaryIdEntity.Id"/>
public long Id => VariableRuntime.Id;
public long Id { get; set; }
/// <inheritdoc cref="Variable.Name"/>
public string Name => VariableRuntime.Name;
public string Name { get; set; }
/// <inheritdoc cref="Variable.CollectGroup"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string CollectGroup => VariableRuntime.CollectGroup;
public string CollectGroup { get; set; }
/// <inheritdoc cref="Variable.BusinessGroup"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string BusinessGroup => VariableRuntime.BusinessGroup;
public string BusinessGroup { get; set; }
/// <inheritdoc cref="Variable.BusinessGroupUpdateTrigger"/>
public bool BusinessGroupUpdateTrigger => VariableRuntime.BusinessGroupUpdateTrigger;
public bool BusinessGroupUpdateTrigger { get; set; }
/// <inheritdoc cref="VariableRuntime.DeviceName"/>
public string DeviceName => VariableRuntime.DeviceName;
public string DeviceName { get; set; }
/// <inheritdoc cref="VariableRuntime.RuntimeType"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
@@ -144,48 +138,48 @@ public class VariableBasicData
/// <inheritdoc cref="Variable.RegisterAddress"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string? RegisterAddress => VariableRuntime.RegisterAddress;
public string? RegisterAddress { get; set; }
/// <inheritdoc cref="Variable.Unit"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string? Unit => VariableRuntime.Unit;
public string? Unit { get; set; }
/// <inheritdoc cref="Variable.Description"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string? Description => VariableRuntime.Description;
public string? Description { get; set; }
/// <inheritdoc cref="Variable.ProtectType"/>
public ProtectTypeEnum ProtectType => VariableRuntime.ProtectType;
public ProtectTypeEnum ProtectType { get; set; }
/// <inheritdoc cref="Variable.DataType"/>
public DataTypeEnum DataType => VariableRuntime.DataType;
public DataTypeEnum DataType { get; set; }
/// <inheritdoc cref="Device.Remark1"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string Remark1 => VariableRuntime.Remark1;
public string Remark1 { get; set; }
/// <inheritdoc cref="Device.Remark2"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string Remark2 => VariableRuntime.Remark2;
public string Remark2 { get; set; }
/// <inheritdoc cref="Device.Remark3"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string Remark3 => VariableRuntime.Remark3;
public string Remark3 { get; set; }
/// <inheritdoc cref="Device.Remark4"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string Remark4 => VariableRuntime.Remark4;
public string Remark4 { get; set; }
/// <inheritdoc cref="Device.Remark5"/>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull)]
public string Remark5 => VariableRuntime.Remark5;
public string Remark5 { get; set; }
}

View File

@@ -10,7 +10,7 @@
using BootstrapBlazor.Components;
using Mapster;
using Riok.Mapperly.Abstractions;
using System.Collections.Concurrent;
@@ -56,7 +56,7 @@ public class DeviceRuntime : Device, IDisposable
/// </summary>
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
public ChannelRuntime? ChannelRuntime { get; set; }
@@ -69,7 +69,7 @@ public class DeviceRuntime : Device, IDisposable
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
public DateTime DeviceStatusChangeTime = DateTime.UnixEpoch.ToLocalTime();
/// <summary>
@@ -154,7 +154,7 @@ public class DeviceRuntime : Device, IDisposable
/// </summary>
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
internal ConcurrentDictionary<string, VariableRuntime>? VariableRuntimes { get; } = new(Environment.ProcessorCount, 1000);
@@ -168,7 +168,7 @@ public class DeviceRuntime : Device, IDisposable
/// </summary>
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
public List<VariableMethod>? ReadVariableMethods { get; set; }
@@ -182,7 +182,7 @@ public class DeviceRuntime : Device, IDisposable
/// </summary>
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
public List<VariableSourceRead>? VariableSourceReads { get; set; }
@@ -191,7 +191,7 @@ public class DeviceRuntime : Device, IDisposable
/// </summary>
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
public List<VariableScriptRead>? VariableScriptReads { get; set; }
@@ -227,13 +227,13 @@ public class DeviceRuntime : Device, IDisposable
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
public IDriver? Driver { get; internal set; }
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
public IRpcDriver? RpcDriver { get; set; }

View File

@@ -8,7 +8,7 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Riok.Mapperly.Abstractions;
using System.Reflection;
@@ -48,6 +48,6 @@ public class DriverMethodInfo
[SugarColumn(IsIgnore = true)]
[System.Text.Json.Serialization.JsonIgnore]
[Newtonsoft.Json.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
public MethodInfo? MethodInfo { get; set; }
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Newtonsoft.Json.Linq;
using ThingsGateway.Gateway.Application.Extensions;
@@ -185,7 +183,7 @@ public partial class VariableRuntime : Variable, IVariable, IDisposable
{
oldAlarm.EventType = EventTypeEnum.Finish;
oldAlarm.EventTime = DateTime.Now;
GlobalData.AlarmChange(this.Adapt<AlarmVariable>());
GlobalData.AlarmChange(this.AdaptAlarmVariable());
}
@@ -215,7 +213,7 @@ public partial class VariableRuntime : Variable, IVariable, IDisposable
{
oldAlarm.EventType = EventTypeEnum.Finish;
oldAlarm.EventTime = DateTime.Now;
GlobalData.AlarmChange(this.Adapt<AlarmVariable>());
GlobalData.AlarmChange(this.AdaptAlarmVariable());
}
GC.SuppressFinalize(this);

View File

@@ -10,7 +10,7 @@
using BootstrapBlazor.Components;
using Mapster;
using Riok.Mapperly.Abstractions;
using ThingsGateway.SqlSugar;
@@ -123,7 +123,7 @@ public partial class VariableRuntime : Variable, IVariable, IDisposable
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
public IVariableSource VariableSource { get => variableSource; set => variableSource = value; }
@@ -132,7 +132,7 @@ public partial class VariableRuntime : Variable, IVariable, IDisposable
/// </summary>
[Newtonsoft.Json.JsonIgnore]
[System.Text.Json.Serialization.JsonIgnore]
[AdaptIgnore]
[MapperIgnore]
[AutoGenerateColumn(Ignore = true)]
public VariableMethod VariableMethod { get => variableMethod; set => variableMethod = value; }

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.Extensions.Logging;
@@ -204,10 +202,10 @@ public class ChannelRuntimeService : IChannelRuntimeService
await WaitLock.WaitAsync().ConfigureAwait(false);
//网关启动时,获取所有通道
var newChannelRuntimes = (await GlobalData.ChannelService.GetAllAsync().ConfigureAwait(false)).Where(a => ids.Contains(a.Id) || !GlobalData.Channels.ContainsKey(a.Id)).Adapt<List<ChannelRuntime>>();
var newChannelRuntimes = (await GlobalData.ChannelService.GetAllAsync().ConfigureAwait(false)).Where(a => ids.Contains(a.Id) || !GlobalData.Channels.ContainsKey(a.Id)).AdaptListChannelRuntime();
var chanelIds = newChannelRuntimes.Select(a => a.Id).ToHashSet();
var newDeviceRuntimes = (await GlobalData.DeviceService.GetAllAsync().ConfigureAwait(false)).Where(a => chanelIds.Contains(a.ChannelId)).Adapt<List<DeviceRuntime>>();
var newDeviceRuntimes = (await GlobalData.DeviceService.GetAllAsync().ConfigureAwait(false)).Where(a => chanelIds.Contains(a.ChannelId)).AdaptListDeviceRuntime();
await RuntimeServiceHelper.InitAsync(newChannelRuntimes, newDeviceRuntimes, _logger).ConfigureAwait(false);

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using MiniExcelLibs;

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using MiniExcelLibs;

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
@@ -363,16 +361,16 @@ internal sealed class AlarmHostedService : BackgroundService, IAlarmHostedServic
//lock (GlobalData. RealAlarmVariables)
{
// 从实时报警列表中移除旧的报警信息,并添加新的报警信息
GlobalData.RealAlarmIdVariables.AddOrUpdate(item.Id, a => item.Adapt<AlarmVariable>(), (a, b) => item.Adapt<AlarmVariable>());
GlobalData.RealAlarmIdVariables.AddOrUpdate(item.Id, a => item.AdaptAlarmVariable(), (a, b) => item.AdaptAlarmVariable());
}
}
else if (item.EventType == EventTypeEnum.Finish)
{
// 如果是需恢复报警事件,则从实时报警列表中移除该变量
GlobalData.RealAlarmIdVariables.TryRemove(item.Id, out _);
//GlobalData.RealAlarmIdVariables.AddOrUpdate(item.Id, a => item.Adapt<AlarmVariable>(), (a, b) => item.Adapt<AlarmVariable>());
//GlobalData.RealAlarmIdVariables.AddOrUpdate(item.Id, a => item.AdaptAlarmVariable(), (a, b) => item.AdaptAlarmVariable());
}
GlobalData.AlarmChange(item.Adapt<AlarmVariable>());
GlobalData.AlarmChange(item.AdaptAlarmVariable());
}
}
@@ -380,11 +378,14 @@ internal sealed class AlarmHostedService : BackgroundService, IAlarmHostedServic
public void ConfirmAlarm(long variableId)
{
// 如果是确认报警事件
if (GlobalData.RealAlarmIdVariables.TryGetValue(variableId, out var variableRuntime))
if (GlobalData.AlarmEnableIdVariables.TryGetValue(variableId, out var variableRuntime))
{
variableRuntime.EventType = EventTypeEnum.Confirm;
variableRuntime.EventTime = DateTime.Now;
GlobalData.AlarmChange(variableRuntime.Adapt<AlarmVariable>());
var data = variableRuntime.AdaptAlarmVariable();
GlobalData.RealAlarmIdVariables.AddOrUpdate(variableId, a => data, (a, b) => data);
GlobalData.AlarmChange(data);
}
}

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using Microsoft.Extensions.Hosting;
using System.Collections.Concurrent;
@@ -445,7 +443,7 @@ internal sealed class DeviceThreadManage : IAsyncDisposable, IDeviceThreadManage
var saveVariables = new List<Variable>();
foreach (var item in saveVariableRuntimes)
{
var data = item.Adapt<Variable>();
var data = item.AdaptVariable();
data.InitValue = item.Value;
saveVariables.Add(data);
}
@@ -599,7 +597,7 @@ internal sealed class DeviceThreadManage : IAsyncDisposable, IDeviceThreadManage
}
else
{
newDeviceRuntime = newDev.Adapt<DeviceRuntime>();
newDeviceRuntime = newDev.AdaptDeviceRuntime();
SetRedundantDevice(deviceRuntime, newDeviceRuntime);
}
}
@@ -620,7 +618,7 @@ internal sealed class DeviceThreadManage : IAsyncDisposable, IDeviceThreadManage
}
else
{
newDeviceRuntime = newDev.Adapt<DeviceRuntime>();
newDeviceRuntime = newDev.AdaptDeviceRuntime();
SetRedundantDevice(deviceRuntime, newDeviceRuntime);
}
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
@@ -42,9 +40,9 @@ internal sealed class GatewayMonitorHostedService : BackgroundService, IGatewayM
{
//网关启动时,获取所有通道
var channelRuntimes = (await GlobalData.ChannelService.GetAllAsync().ConfigureAwait(false)).Adapt<List<ChannelRuntime>>();
var deviceRuntimes = (await GlobalData.DeviceService.GetAllAsync().ConfigureAwait(false)).Adapt<List<DeviceRuntime>>();
var variableRuntimes = (await GlobalData.VariableService.GetAllAsync().ConfigureAwait(false)).Adapt<List<VariableRuntime>>();
var channelRuntimes = (await GlobalData.ChannelService.GetAllAsync().ConfigureAwait(false)).AdaptListChannelRuntime();
var deviceRuntimes = (await GlobalData.DeviceService.GetAllAsync().ConfigureAwait(false)).AdaptListDeviceRuntime();
var variableRuntimes = (await GlobalData.VariableService.GetAllAsync().ConfigureAwait(false)).AdaptListVariableRuntime();
foreach (var channelRuntime in channelRuntimes)
{
try

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
@@ -158,7 +156,7 @@ internal sealed class RedundancyHostedService : BackgroundService, IRedundancyHo
// 如果 online 为 true表示设备在线
if (online)
{
var deviceRunTimes = GlobalData.ReadOnlyIdDevices.Where(a => a.Value.IsCollect == true).Select(a => a.Value).Adapt<List<DeviceDataWithValue>>();
var deviceRunTimes = GlobalData.ReadOnlyIdDevices.Where(a => a.Value.IsCollect == true).Select(a => a.Value).AdaptListDeviceDataWithValue();
foreach (var item in TcpDmtpService.Clients)
{
@@ -370,7 +368,7 @@ internal sealed class RedundancyHostedService : BackgroundService, IRedundancyHo
private async Task BeforeStartAsync()
{
RedundancyOptions = (await _redundancyService.GetRedundancyAsync().ConfigureAwait(false)).Adapt<RedundancyOptions>();
RedundancyOptions = (await _redundancyService.GetRedundancyAsync().ConfigureAwait(false)).AdaptRedundancyOptions();
if (RedundancyOptions?.Enable == true)
{

View File

@@ -11,8 +11,6 @@
using BootstrapBlazor.Components;
using Mapster;
using Microsoft.Extensions.Logging;
using ThingsGateway.Extension.Generic;
@@ -38,7 +36,7 @@ internal static class RuntimeServiceHelper
{
newDeviceRuntime.Init(newChannelRuntime);
var newVariableRuntimes = (await GlobalData.VariableService.GetAllAsync(newDeviceRuntime.Id).ConfigureAwait(false)).Adapt<List<VariableRuntime>>();
var newVariableRuntimes = (await GlobalData.VariableService.GetAllAsync(newDeviceRuntime.Id).ConfigureAwait(false)).AdaptListVariableRuntime();
newVariableRuntimes.ParallelForEach(item =>
{
@@ -91,7 +89,7 @@ internal static class RuntimeServiceHelper
{
newDeviceRuntime.Init(newChannelRuntime);
var newVariableRuntimes = (await GlobalData.VariableService.GetAllAsync(newDeviceRuntime.Id).ConfigureAwait(false)).Adapt<List<VariableRuntime>>();
var newVariableRuntimes = (await GlobalData.VariableService.GetAllAsync(newDeviceRuntime.Id).ConfigureAwait(false)).AdaptListVariableRuntime();
newVariableRuntimes.ParallelForEach(item =>
{
@@ -169,13 +167,13 @@ internal static class RuntimeServiceHelper
public static async Task<List<ChannelRuntime>> GetNewChannelRuntimesAsync(HashSet<long> ids)
{
var newChannelRuntimes = (await GlobalData.ChannelService.GetAllAsync().ConfigureAwait(false)).Where(a => ids.Contains(a.Id)).Adapt<List<ChannelRuntime>>();
var newChannelRuntimes = (await GlobalData.ChannelService.GetAllAsync().ConfigureAwait(false)).Where(a => ids.Contains(a.Id)).AdaptListChannelRuntime();
return newChannelRuntimes;
}
public static async Task<List<DeviceRuntime>> GetNewDeviceRuntimesAsync(HashSet<long> deviceids)
{
var newDeviceRuntimes = (await GlobalData.DeviceService.GetAllAsync().ConfigureAwait(false)).Where(a => deviceids.Contains(a.Id)).Adapt<List<DeviceRuntime>>();
var newDeviceRuntimes = (await GlobalData.DeviceService.GetAllAsync().ConfigureAwait(false)).Where(a => deviceids.Contains(a.Id)).AdaptListDeviceRuntime();
return newDeviceRuntimes;
}
@@ -269,10 +267,10 @@ internal static class RuntimeServiceHelper
public static async Task RemoveDeviceAsync(HashSet<long> newDeciceIds)
{
//先找出线程管理器,停止
var deviceRuntimes = GlobalData.IdDevices.Where(a => newDeciceIds.Contains(a.Key)).Select(a => a.Value).ToList();
var deviceRuntimes = GlobalData.IdDevices.Where(a => newDeciceIds.Contains(a.Key)).Select(a => a.Value);
await RemoveDeviceAsync(deviceRuntimes).ConfigureAwait(false);
}
public static async Task RemoveDeviceAsync(List<DeviceRuntime> deviceRuntimes)
public static async Task RemoveDeviceAsync(IEnumerable<DeviceRuntime> deviceRuntimes)
{
var groups = GlobalData.GetDeviceThreadManages(deviceRuntimes);
foreach (var group in groups)

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.Extensions.Logging;
@@ -38,7 +36,7 @@ public class VariableRuntimeService : IVariableRuntimeService
var result = await GlobalData.VariableService.BatchSaveVariableAsync(input.Where(a => !a.DynamicVariable).ToList(), type).ConfigureAwait(false);
var newVariableRuntimes = input.Adapt<List<VariableRuntime>>();
var newVariableRuntimes = input.AdaptListVariableRuntime();
var variableIds = newVariableRuntimes.Select(a => a.Id).ToHashSet();
//获取变量,先找到原插件线程,然后修改插件线程内的字典,再改动全局字典,最后刷新插件
@@ -73,7 +71,7 @@ public class VariableRuntimeService : IVariableRuntimeService
using var db = DbContext.GetDB<Variable>();
var ids = models.Select(a => a.Id).ToHashSet();
var newVariableRuntimes = (await db.Queryable<Variable>().Where(a => ids.Contains(a.Id)).ToListAsync(cancellationToken).ConfigureAwait(false)).Adapt<List<VariableRuntime>>();
var newVariableRuntimes = (await db.Queryable<Variable>().Where(a => ids.Contains(a.Id)).ToListAsync(cancellationToken).ConfigureAwait(false)).AdaptListVariableRuntime();
var variableIds = newVariableRuntimes.Select(a => a.Id).ToHashSet();
@@ -140,7 +138,7 @@ public class VariableRuntimeService : IVariableRuntimeService
using var db = DbContext.GetDB<Variable>();
var newVariableRuntimes = (await db.Queryable<Variable>().Where(a => result.Contains(a.Id)).ToListAsync(cancellationToken).ConfigureAwait(false)).Adapt<List<VariableRuntime>>();
var newVariableRuntimes = (await db.Queryable<Variable>().Where(a => result.Contains(a.Id)).ToListAsync(cancellationToken).ConfigureAwait(false)).AdaptListVariableRuntime();
var variableIds = newVariableRuntimes.Select(a => a.Id).ToHashSet();
@@ -176,20 +174,20 @@ public class VariableRuntimeService : IVariableRuntimeService
var datas = await GlobalData.VariableService.InsertTestDataAsync(testVariableCount, testDeviceCount, slaveUrl, businessEnable).ConfigureAwait(false);
{
var newChannelRuntimes = datas.Item1.Adapt<List<ChannelRuntime>>();
var newChannelRuntimes = datas.Item1.AdaptListChannelRuntime();
//批量修改之后,需要重新加载通道
RuntimeServiceHelper.Init(newChannelRuntimes);
{
var newDeviceRuntimes = datas.Item2.Adapt<List<DeviceRuntime>>();
var newDeviceRuntimes = datas.Item2.AdaptListDeviceRuntime();
RuntimeServiceHelper.Init(newDeviceRuntimes);
}
{
var newVariableRuntimes = datas.Item3.Adapt<List<VariableRuntime>>();
var newVariableRuntimes = datas.Item3.AdaptListVariableRuntime();
RuntimeServiceHelper.Init(newVariableRuntimes);
}
@@ -230,7 +228,7 @@ public class VariableRuntimeService : IVariableRuntimeService
using var db = DbContext.GetDB<Variable>();
var newVariableRuntimes = (await db.Queryable<Variable>().Where(a => a.Id == input.Id).ToListAsync(cancellationToken).ConfigureAwait(false)).Adapt<List<VariableRuntime>>();
var newVariableRuntimes = (await db.Queryable<Variable>().Where(a => a.Id == input.Id).ToListAsync(cancellationToken).ConfigureAwait(false)).AdaptListVariableRuntime();
var variableIds = newVariableRuntimes.Select(a => a.Id).ToHashSet();

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using MiniExcelLibs;

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
@@ -54,11 +52,6 @@ public class Startup : AppStartup
//底层多语言配置
Foundation.LocalizerUtil.SetLocalizerFactory((a) => App.CreateLocalizerByType(a));
TypeAdapterConfig.GlobalSettings.Scan(App.Assemblies.ToArray());
// 配置默认全局映射(支持覆盖)
TypeAdapterConfig.GlobalSettings.Default
.PreserveReference(true);
//运行日志写入数据库配置
services.AddDatabaseLogging<BackendLogDatabaseLoggingWriter>(options =>
{

View File

@@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
<PackageReference Include="Riok.Mapperly" Version="4.2.1" ExcludeAssets="runtime" PrivateAssets="all" />
<PackageReference Include="Rougamo.Fody" Version="5.0.1" />
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.11" />
<PackageReference Include="TouchSocket.WebApi.Swagger" Version="3.1.11" />

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using ThingsGateway.Admin.Application;
using ThingsGateway.Foundation;
using ThingsGateway.NewLife.Json.Extension;
@@ -50,7 +48,7 @@ public partial class TcpServiceComponent : IDriverUIBase
if (TcpServiceChannel != null)
{
var clients = TcpServiceChannel.Clients.ToList();
var data = clients.Adapt<List<TcpSessionClientDto>>();
var data = clients.AdaptListTcpSessionClientDto();
for (int i = 0; i < clients.Count; i++)
{
var client = clients[i];

View File

@@ -8,26 +8,15 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Riok.Mapperly.Abstractions;
namespace ThingsGateway.Gateway.Application;
using ThingsGateway.Foundation;
public class VariableMapper : IRegister
namespace ThingsGateway.Gateway.Razor;
[Mapper(UseDeepCloning = true, EnumMappingStrategy = EnumMappingStrategy.ByName, RequiredMappingStrategy = RequiredMappingStrategy.None)]
public static partial class GatewayMapper
{
/// <inheritdoc/>
public void Register(TypeAdapterConfig config)
{
config.ForType<Variable, VariableRuntime>()
.Map(dest => dest.Value, src => src.InitValue);
public static partial List<TcpSessionClientDto> AdaptListTcpSessionClientDto(this List<TcpSessionClientChannel> src);
config.ForType<VariableRuntime, VariableRuntime>()
.Ignore(dest => dest.DeviceRuntime);
config.ForType<VariableRuntime, VariableBasicData>()
.BeforeMapping((a, b) => b.VariableRuntime = a);
config.ForType<DeviceRuntime, DeviceBasicData>()
.BeforeMapping((a, b) => b.DeviceRuntime = a);
}
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using ThingsGateway.Admin.Application;
namespace ThingsGateway.Gateway.Razor;
@@ -51,14 +49,14 @@ public partial class ChannelCopyComponent
Dictionary<Device, List<Variable>> devices = new();
for (int i = 0; i < CopyCount; i++)
{
Channel channel = Model.Adapt<Channel>();
Channel channel = Model.AdaptChannel();
channel.Id = CommonUtils.GetSingleId();
channel.Name = $"{CopyChannelNamePrefix}{CopyChannelNameSuffixNumber + i}";
int index = 0;
foreach (var item in Devices)
{
Device device = item.Key.Adapt<Device>();
Device device = item.Key.AdaptDevice();
device.Id = CommonUtils.GetSingleId();
device.Name = $"{channel.Name}_{CopyDeviceNamePrefix}{CopyDeviceNameSuffixNumber + (index++)}";
device.ChannelId = channel.Id;
@@ -66,7 +64,7 @@ public partial class ChannelCopyComponent
foreach (var variable in item.Value)
{
Variable v = variable.Adapt<Variable>();
Variable v = variable.AdaptVariable();
v.Id = CommonUtils.GetSingleId();
v.DeviceId = device.Id;
variables.Add(v);

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using ThingsGateway.Admin.Application;
@@ -22,7 +20,7 @@ public partial class ChannelTable : IDisposable
{
private static void BeforeShowEditDialogCallback(ITableEditDialogOption<ChannelRuntime> tableEditDialogOption)
{
tableEditDialogOption.Model = tableEditDialogOption.Model.Adapt<ChannelRuntime>();
tableEditDialogOption.Model = tableEditDialogOption.Model.AdaptChannelRuntime();
}
public bool Disposed { get; set; }
@@ -113,10 +111,10 @@ public partial class ChannelTable : IDisposable
Channel oneModel = null;
Dictionary<Device, List<Variable>> deviceDict = new();
var channelRuntime = channels.FirstOrDefault();
oneModel = channelRuntime.Adapt<Channel>();
oneModel = channelRuntime.AdaptChannel();
oneModel.Id = 0;
deviceDict = channelRuntime.ReadDeviceRuntimes.ToDictionary(a => a.Value.Adapt<Device>(), a => a.Value.ReadOnlyVariableRuntimes.Select(a => a.Value).Adapt<List<Variable>>());
deviceDict = channelRuntime.ReadDeviceRuntimes.ToDictionary(a => a.Value.AdaptDevice(), a => a.Value.ReadOnlyVariableRuntimes.Select(a => a.Value).AdaptListVariable());
var op = new DialogOption()
@@ -157,9 +155,9 @@ public partial class ChannelTable : IDisposable
await ToastService.Warning(null, RazorLocalizer["PleaseSelect"]);
return;
}
changedModels = changedModels.Adapt<List<Channel>>();
oldModel = oldModel.Adapt<Channel>();
var oneModel = oldModel.Adapt<Channel>();//默认值显示第一个
changedModels = changedModels.AdaptListChannel();
oldModel = oldModel.AdaptChannel();
var oneModel = oldModel.AdaptChannel();//默认值显示第一个
var op = new DialogOption()
{
@@ -215,7 +213,7 @@ public partial class ChannelTable : IDisposable
{
try
{
channel = channel.Adapt<Channel>();
channel = channel.AdaptChannel();
return await Task.Run(() => GlobalData.ChannelRuntimeService.SaveChannelAsync(channel, itemChangedType, AutoRestartThread));
}
catch (Exception ex)
@@ -229,7 +227,7 @@ public partial class ChannelTable : IDisposable
private Task<ChannelRuntime> OnAdd()
{
return Task.FromResult(ChannelDeviceHelpers.GetChannelModel(ItemChangedType.Add, SelectModel).Adapt<ChannelRuntime>());
return Task.FromResult(ChannelDeviceHelpers.GetChannelModel(ItemChangedType.Add, SelectModel).AdaptChannelRuntime());
}
#region

View File

@@ -1,5 +1,4 @@
using Mapster;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
@@ -19,7 +18,7 @@ namespace ThingsGateway.Gateway.Razor
Channel oneModel = null;
if (channelDeviceTreeItem.TryGetChannelRuntime(out var channelRuntime))
{
oneModel = channelRuntime.Adapt<Channel>();
oneModel = channelRuntime.AdaptChannel();
if (itemChangedType == ItemChangedType.Add)
{
oneModel.Id = 0;
@@ -28,7 +27,7 @@ namespace ThingsGateway.Gateway.Razor
}
else if (channelDeviceTreeItem.TryGetDeviceRuntime(out var deviceRuntime))
{
oneModel = deviceRuntime.ChannelRuntime?.Adapt<Channel>() ?? new();
oneModel = deviceRuntime.ChannelRuntime?.AdaptChannel() ?? new();
if (itemChangedType == ItemChangedType.Add)
{
oneModel.Id = 0;
@@ -51,7 +50,7 @@ namespace ThingsGateway.Gateway.Razor
Device oneModel = null;
if (channelDeviceTreeItem.TryGetDeviceRuntime(out var deviceRuntime))
{
oneModel = deviceRuntime.Adapt<Device>();
oneModel = deviceRuntime.AdaptDevice();
if (itemChangedType == ItemChangedType.Add)
{
oneModel.Id = 0;

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Web;
@@ -145,10 +143,10 @@ public partial class ChannelDeviceTree
if (channelDeviceTreeItem.TryGetChannelRuntime(out var channelRuntime))
{
oneModel = channelRuntime.Adapt<Channel>();
oneModel = channelRuntime.AdaptChannel();
oneModel.Id = 0;
deviceDict = channelRuntime.ReadDeviceRuntimes.ToDictionary(a => a.Value.Adapt<Device>(), a => a.Value.ReadOnlyVariableRuntimes.Select(a => a.Value).Adapt<List<Variable>>());
deviceDict = channelRuntime.ReadDeviceRuntimes.ToDictionary(a => a.Value.AdaptDevice(), a => a.Value.ReadOnlyVariableRuntimes.Select(a => a.Value).AdaptListVariable());
}
else
{
@@ -210,7 +208,7 @@ public partial class ChannelDeviceTree
models = data.Where(a => a.PluginName == pluginName);
oldModel = models.FirstOrDefault();
changedModels = models;
oneModel = oldModel.Adapt<Channel>();
oneModel = oldModel.AdaptChannel();
}
else if (channelDeviceTreeItem.TryGetPluginType(out var pluginType))
@@ -221,7 +219,7 @@ public partial class ChannelDeviceTree
models = data.Where(a => a.PluginType == pluginType);
oldModel = models.FirstOrDefault();
changedModels = models;
oneModel = oldModel.Adapt<Channel>();
oneModel = oldModel.AdaptChannel();
}
@@ -230,8 +228,8 @@ public partial class ChannelDeviceTree
return;
}
changedModels = changedModels.Adapt<List<Channel>>();
oldModel = oldModel.Adapt<Channel>();
changedModels = changedModels.AdaptListChannel();
oldModel = oldModel.AdaptChannel();
var op = new DialogOption()
{
IsScrolling = false,
@@ -628,10 +626,10 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e =>
if (channelDeviceTreeItem.TryGetDeviceRuntime(out var deviceRuntime))
{
oneModel = deviceRuntime.Adapt<Device>();
oneModel = deviceRuntime.AdaptDevice();
oneModel.Id = 0;
variables = deviceRuntime.ReadOnlyVariableRuntimes.Select(a => a.Value).Adapt<List<Variable>>();
variables = deviceRuntime.ReadOnlyVariableRuntimes.Select(a => a.Value).AdaptListVariable();
}
else
{
@@ -672,7 +670,7 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e =>
if (channelDeviceTreeItem.TryGetDeviceRuntime(out var deviceRuntime))
{
oneModel = deviceRuntime.Adapt<Device>();
oneModel = deviceRuntime.AdaptDevice();
if (itemChangedType == ItemChangedType.Add)
{
oneModel.Id = 0;
@@ -738,7 +736,7 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e =>
models = data.Where(a => a.ChannelId == channelRuntime.Id);
oldModel = models.FirstOrDefault();
changedModels = models;
oneModel = oldModel.Adapt<Device>();
oneModel = oldModel.AdaptDevice();
}
//批量编辑只有分类和插件名称节点
else if (channelDeviceTreeItem.TryGetPluginName(out var pluginName))
@@ -748,7 +746,7 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e =>
models = data.Where(a => a.PluginName == pluginName); ;
oldModel = models.FirstOrDefault();
changedModels = models;
oneModel = oldModel.Adapt<Device>();
oneModel = oldModel.AdaptDevice();
}
else if (channelDeviceTreeItem.TryGetPluginType(out var pluginType))
@@ -759,7 +757,7 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e =>
models = data.Where(a => a.PluginType == pluginType); ;
oldModel = models.FirstOrDefault();
changedModels = models;
oneModel = oldModel.Adapt<Device>();
oneModel = oldModel.AdaptDevice();
}
@@ -768,8 +766,8 @@ EventCallback.Factory.Create<MouseEventArgs>(this, async e =>
return;
}
changedModels = changedModels.Adapt<List<Device>>();
oldModel = oldModel.Adapt<Device>();
changedModels = changedModels.AdaptListDevice();
oldModel = oldModel.AdaptDevice();
op.Component = BootstrapDynamicComponent.CreateComponent<DeviceEditComponent>(new Dictionary<string, object?>
{
{nameof(DeviceEditComponent.OnValidSubmit), async () =>

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using ThingsGateway.Admin.Application;
namespace ThingsGateway.Gateway.Razor;
@@ -47,14 +45,14 @@ public partial class DeviceCopyComponent
Dictionary<Device, List<Variable>> devices = new();
for (int i = 0; i < CopyCount; i++)
{
Device device = Model.Adapt<Device>();
Device device = Model.AdaptDevice();
device.Id = CommonUtils.GetSingleId();
device.Name = $"{CopyDeviceNamePrefix}{CopyDeviceNameSuffixNumber + i}";
List<Variable> variables = new();
foreach (var item in Variables)
{
Variable v = item.Adapt<Variable>();
Variable v = item.AdaptVariable();
v.Id = CommonUtils.GetSingleId();
v.DeviceId = device.Id;
variables.Add(v);

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using ThingsGateway.Admin.Application;
@@ -22,7 +20,7 @@ public partial class DeviceTable : IDisposable
{
private static void BeforeShowEditDialogCallback(ITableEditDialogOption<DeviceRuntime> tableEditDialogOption)
{
tableEditDialogOption.Model = tableEditDialogOption.Model.Adapt<DeviceRuntime>();
tableEditDialogOption.Model = tableEditDialogOption.Model.AdaptDeviceRuntime();
}
public bool Disposed { get; set; }
@@ -113,10 +111,10 @@ public partial class DeviceTable : IDisposable
Device oneModel = null;
List<Variable> variables = new();
var deviceRuntime = devices.FirstOrDefault();
oneModel = deviceRuntime.Adapt<Device>();
oneModel = deviceRuntime.AdaptDevice();
oneModel.Id = 0;
variables = deviceRuntime.ReadOnlyVariableRuntimes.Select(a => a.Value).Adapt<List<Variable>>();
variables = deviceRuntime.ReadOnlyVariableRuntimes.Select(a => a.Value).AdaptListVariable();
var op = new DialogOption()
@@ -156,9 +154,9 @@ public partial class DeviceTable : IDisposable
await ToastService.Warning(null, RazorLocalizer["PleaseSelect"]);
return;
}
changedModels = changedModels.Adapt<List<Device>>();
oldModel = oldModel.Adapt<Device>();
var oneModel = oldModel.Adapt<Device>();//默认值显示第一个
changedModels = changedModels.AdaptListDevice();
oldModel = oldModel.AdaptDevice();
var oneModel = oldModel.AdaptDevice();//默认值显示第一个
var op = new DialogOption()
{
@@ -215,7 +213,7 @@ public partial class DeviceTable : IDisposable
try
{
device.DevicePropertys = PluginServiceUtil.SetDict(device.ModelValueValidateForm.Value);
device = device.Adapt<Device>();
device = device.AdaptDevice();
return await Task.Run(() => GlobalData.DeviceRuntimeService.SaveDeviceAsync(device, itemChangedType, AutoRestartThread));
}
catch (Exception ex)
@@ -229,7 +227,7 @@ public partial class DeviceTable : IDisposable
private Task<DeviceRuntime> OnAdd()
{
return Task.FromResult(ChannelDeviceHelpers.GetDeviceModel(ItemChangedType.Add, SelectModel).Adapt<DeviceRuntime>());
return Task.FromResult(ChannelDeviceHelpers.GetDeviceModel(ItemChangedType.Add, SelectModel).AdaptDeviceRuntime());
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using ThingsGateway.Admin.Application;
namespace ThingsGateway.Gateway.Razor;
@@ -42,7 +40,7 @@ public partial class VariableCopyComponent
List<Variable> variables = new();
for (int i = 0; i < CopyCount; i++)
{
var variable = Model.Adapt<List<Variable>>();
var variable = Model.AdaptListVariable();
foreach (var item in variable)
{
item.Id = CommonUtils.GetSingleId();

View File

@@ -1,6 +1,5 @@
@namespace ThingsGateway.Gateway.Razor
@using System.Text.Json.Nodes
@using Mapster
@using Microsoft.Extensions.Hosting
@using ThingsGateway.Admin.Application
@using ThingsGateway.Admin.Razor

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.Extensions.Options;
@@ -25,7 +23,7 @@ public partial class VariableRuntimeInfo : IDisposable
private static void BeforeShowEditDialogCallback(ITableEditDialogOption<VariableRuntime> tableEditDialogOption)
{
tableEditDialogOption.Model = tableEditDialogOption.Model.Adapt<VariableRuntime>();
tableEditDialogOption.Model = tableEditDialogOption.Model.AdaptVariableRuntime();
}
[Inject]
@@ -217,9 +215,9 @@ public partial class VariableRuntimeInfo : IDisposable
await ToastService.Warning(null, RazorLocalizer["PleaseSelect"]);
return;
}
variables = variables.Where(a => !a.DynamicVariable).Adapt<List<Variable>>();
oldModel = oldModel.Adapt<Variable>();
var model = oldModel.Adapt<Variable>();//默认值显示第一个
variables = variables.Where(a => !a.DynamicVariable).AdaptListVariable();
oldModel = oldModel.AdaptVariable();
var model = oldModel.AdaptVariable();//默认值显示第一个
op.Component = BootstrapDynamicComponent.CreateComponent<VariableEditComponent>(new Dictionary<string, object?>
{
{nameof(VariableEditComponent.OnValidSubmit), async () =>
@@ -272,7 +270,7 @@ public partial class VariableRuntimeInfo : IDisposable
}
variable.VariablePropertys = PluginServiceUtil.SetDict(variable.VariablePropertyModels);
variable = variable.Adapt<Variable>();
variable = variable.AdaptVariable();
return await Task.Run(() => GlobalData.VariableRuntimeService.SaveVariableAsync(variable, itemChangedType, AutoRestartThread, default));
}
catch (Exception ex)

View File

@@ -9,8 +9,6 @@
//------------------------------------------------------------------------------
#pragma warning disable CA2007 // 考虑对等待的任务调用 ConfigureAwait
using Mapster;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Web;
@@ -47,7 +45,7 @@ public partial class RedundancyOptionsPage
{
await base.OnInitializedAsync();
HeaderText = GatewayLocalizer[nameof(HeaderText)];
Model = (await RedundancyService.GetRedundancyAsync()).Adapt<RedundancyOptions>();
Model = (await RedundancyService.GetRedundancyAsync()).AdaptRedundancyOptions();
}
[Inject]

View File

@@ -1,7 +1,6 @@
@page "/gateway/plugindebug"
@namespace ThingsGateway.Gateway.Razor
@using System.Linq.Expressions;
@using Mapster;
@using System.IO;
@using Microsoft.AspNetCore.Authorization;

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using ThingsGateway.NewLife.Extension;
namespace ThingsGateway.Gateway.Razor;
@@ -28,7 +26,7 @@ public partial class PluginDebugPage
/// <inheritdoc/>
protected override void OnParametersSet()
{
var pluginInfos = PluginService.GetList().Adapt<List<PluginInfo>>();
var pluginInfos = PluginService.GetList().AdaptListPluginInfo();
foreach (var pluginInfo in pluginInfos.ToList())
{

View File

@@ -10,6 +10,7 @@
<ProjectReference Include="..\ThingsGateway.Blazor.Diagrams\ThingsGateway.Blazor.Diagrams.csproj" />
<ProjectReference Include="..\ThingsGateway.Gateway.Application\ThingsGateway.Gateway.Application.csproj" />
<PackageReference Include="BootstrapBlazor.UniverSheet" Version="9.0.5" />
<PackageReference Include="Riok.Mapperly" Version="4.2.1" ExcludeAssets="runtime" PrivateAssets="all" />
<PackageReference Include="BootstrapBlazor.WinBox" Version="9.0.7" />
<PackageReference Include="BootstrapBlazor.CodeEditor" Version="9.0.1" />
<ProjectReference Include="..\..\Admin\ThingsGateway.Admin.Razor\ThingsGateway.Admin.Razor.csproj" />

View File

@@ -0,0 +1,274 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
//------------------------------------------------------------------------------
using Newtonsoft.Json.Linq;
using ThingsGateway.NewLife.Extension;
using ThingsGateway.Plugin.QuestDB;
using ThingsGateway.Plugin.SqlDB;
namespace ThingsGateway.Plugin.DB;
internal static class Helper
{
#region
public static SQLHistoryValue AdaptSQLHistoryValue(this VariableRuntime src)
{
var dest = new SQLHistoryValue();
dest.Id = src.Id;
dest.Value = GetValue(src.Value);
dest.CreateTime = DateTime.Now;
dest.CollectTime = src.CollectTime;
dest.DeviceName = src.DeviceName;
dest.IsOnline = src.IsOnline;
dest.Name = src.Name;
return dest;
}
public static List<SQLHistoryValue> AdaptListSQLHistoryValue(this IEnumerable<VariableRuntime> src)
{
return Enumerable.ToList(
Enumerable.Select(src, x => AdaptSQLHistoryValue(x))
);
}
public static SQLHistoryValue AdaptSQLHistoryValue(this VariableBasicData src)
{
var dest = new SQLHistoryValue();
dest.Id = src.Id;
dest.Value = GetValue(src.Value);
dest.CreateTime = DateTime.Now;
dest.CollectTime = src.CollectTime;
dest.DeviceName = src.DeviceName;
dest.IsOnline = src.IsOnline;
dest.Name = src.Name;
return dest;
}
public static List<SQLHistoryValue> AdaptListSQLHistoryValue(this IEnumerable<VariableBasicData> src)
{
return Enumerable.ToList(
Enumerable.Select(src, x => AdaptSQLHistoryValue(x))
);
}
public static SQLNumberHistoryValue AdaptSQLNumberHistoryValue(this VariableRuntime src)
{
var dest = new SQLNumberHistoryValue();
dest.Id = src.Id;
dest.Value = src.Value.GetType() == typeof(bool) ? ConvertUtility.Convert.ToBoolean(src.Value, false) ? 1 : 0 : ConvertUtility.Convert.ToDecimal(src.Value, 0);
dest.CreateTime = DateTime.Now;
dest.CollectTime = src.CollectTime;
dest.DeviceName = src.DeviceName;
dest.IsOnline = src.IsOnline;
dest.Name = src.Name;
return dest;
}
public static List<SQLNumberHistoryValue> AdaptListSQLNumberHistoryValue(this IEnumerable<VariableRuntime> src)
{
return Enumerable.ToList(
Enumerable.Select(src, x => AdaptSQLNumberHistoryValue(x))
);
}
public static SQLNumberHistoryValue AdaptSQLNumberHistoryValue(this VariableBasicData src)
{
var dest = new SQLNumberHistoryValue();
dest.Id = src.Id;
dest.Value = src.Value.GetType() == typeof(bool) ? ConvertUtility.Convert.ToBoolean(src.Value, false) ? 1 : 0 : ConvertUtility.Convert.ToDecimal(src.Value, 0);
dest.CreateTime = DateTime.Now;
dest.CollectTime = src.CollectTime;
dest.DeviceName = src.DeviceName;
dest.IsOnline = src.IsOnline;
dest.Name = src.Name;
return dest;
}
public static List<SQLNumberHistoryValue> AdaptListSQLNumberHistoryValue(this IEnumerable<VariableBasicData> src)
{
return Enumerable.ToList(
Enumerable.Select(src, x => AdaptSQLNumberHistoryValue(x))
);
}
public static SQLRealValue AdaptSQLRealValue(this VariableBasicData src)
{
var dest = new SQLRealValue();
dest.Id = src.Id;
dest.Value = GetValue(src.Value);
dest.CollectTime = src.CollectTime;
dest.DeviceName = src.DeviceName;
dest.IsOnline = src.IsOnline;
dest.Name = src.Name;
return dest;
}
public static List<SQLRealValue> AdaptListSQLRealValue(this IEnumerable<VariableBasicData> src)
{
return Enumerable.ToList(
Enumerable.Select(src, x => AdaptSQLRealValue(x))
);
}
public static SQLRealValue AdaptSQLRealValue(this VariableRuntime src)
{
var dest = new SQLRealValue();
dest.Id = src.Id;
dest.Value = GetValue(src.Value);
dest.CollectTime = src.CollectTime;
dest.DeviceName = src.DeviceName;
dest.IsOnline = src.IsOnline;
dest.Name = src.Name;
return dest;
}
public static List<SQLRealValue> AdaptListSQLRealValue(this IEnumerable<VariableRuntime> src)
{
return Enumerable.ToList(
Enumerable.Select(src, x => AdaptSQLRealValue(x))
);
}
#endregion
#region
public static QuestDBHistoryValue AdaptQuestDBHistoryValue(this VariableRuntime src)
{
var dest = new QuestDBHistoryValue();
dest.Id = src.Id;
dest.Value = GetValue(src.Value);
dest.CreateTime = DateTime.UtcNow;
dest.CollectTime = src.CollectTime < DateTime.MinValue ? UtcTime1970 : src.CollectTime;
dest.DeviceName = src.DeviceName;
dest.IsOnline = src.IsOnline;
dest.Name = src.Name;
return dest;
}
public static List<QuestDBHistoryValue> AdaptListQuestDBHistoryValue(this IEnumerable<VariableRuntime> src)
{
return Enumerable.ToList(
Enumerable.Select(src, x => AdaptQuestDBHistoryValue(x))
);
}
public static QuestDBHistoryValue AdaptQuestDBHistoryValue(this VariableBasicData src)
{
var dest = new QuestDBHistoryValue();
dest.Id = src.Id;
dest.Value = GetValue(src.Value);
dest.CreateTime = DateTime.UtcNow;
dest.CollectTime = src.CollectTime < DateTime.MinValue ? UtcTime1970 : src.CollectTime;
dest.DeviceName = src.DeviceName;
dest.IsOnline = src.IsOnline;
dest.Name = src.Name;
return dest;
}
public static List<QuestDBHistoryValue> AdaptListQuestDBHistoryValue(this IEnumerable<VariableBasicData> src)
{
return Enumerable.ToList(
Enumerable.Select(src, x => AdaptQuestDBHistoryValue(x))
);
}
public static QuestDBNumberHistoryValue AdaptQuestDBNumberHistoryValue(this VariableRuntime src)
{
var dest = new QuestDBNumberHistoryValue();
dest.Id = src.Id;
dest.Value = src.Value.GetType() == typeof(bool) ? ConvertUtility.Convert.ToBoolean(src.Value, false) ? 1 : 0 : ConvertUtility.Convert.ToDecimal(src.Value, 0);
dest.CreateTime = DateTime.UtcNow;
dest.CollectTime = src.CollectTime < DateTime.MinValue ? UtcTime1970 : src.CollectTime;
dest.DeviceName = src.DeviceName;
dest.IsOnline = src.IsOnline;
dest.Name = src.Name;
return dest;
}
public static List<QuestDBNumberHistoryValue> AdaptListQuestDBNumberHistoryValue(this IEnumerable<VariableRuntime> src)
{
return Enumerable.ToList(
Enumerable.Select(src, x => AdaptQuestDBNumberHistoryValue(x))
);
}
public static QuestDBNumberHistoryValue AdaptQuestDBNumberHistoryValue(this VariableBasicData src)
{
var dest = new QuestDBNumberHistoryValue();
dest.Id = src.Id;
dest.Value = src.Value.GetType() == typeof(bool) ? ConvertUtility.Convert.ToBoolean(src.Value, false) ? 1 : 0 : ConvertUtility.Convert.ToDecimal(src.Value, 0);
dest.CreateTime = DateTime.UtcNow;
dest.CollectTime = src.CollectTime < DateTime.MinValue ? UtcTime1970 : src.CollectTime;
dest.DeviceName = src.DeviceName;
dest.IsOnline = src.IsOnline;
dest.Name = src.Name;
return dest;
}
public static List<QuestDBNumberHistoryValue> AdaptListQuestDBNumberHistoryValue(this IEnumerable<VariableBasicData> src)
{
return Enumerable.ToList(
Enumerable.Select(src, x => AdaptQuestDBNumberHistoryValue(x))
);
}
static DateTime UtcTime1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
#endregion
private static string GetValue(object src)
{
if (src != null)
{
if (src is string strValue)
{
return strValue;
}
else if (src is bool boolValue)
{
return boolValue ? "1" : "0";
}
else
{
return JToken.FromObject(src).ToString();
}
}
else
{
return string.Empty;
}
}
}

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using ThingsGateway.Admin.Application;
using ThingsGateway.Debug;
using ThingsGateway.Foundation;
@@ -70,39 +68,6 @@ public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableMode
protected override async Task InitChannelAsync(IChannel? channel, CancellationToken cancellationToken)
{
_db = BusinessDatabaseUtil.GetDb(_driverPropertys.DbType, _driverPropertys.BigTextConnectStr);
_config = new TypeAdapterConfig();
DateTime utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
_config.ForType<VariableRuntime, QuestDBHistoryValue>()
//.Map(dest => dest.Id, src => CommonUtils.GetSingleId())
.Map(dest => dest.Id, src => src.Id)//Id更改为变量Id
.Map(dest => dest.Value, src => src.Value == null ? string.Empty : src.Value.ToString() ?? string.Empty)
.Map(dest => dest.CollectTime, (src) => src.CollectTime < DateTime.MinValue ? utcTime : src.CollectTime)//注意sqlsugar插入时无时区直接utc时间
.Map(dest => dest.CreateTime, (src) => DateTime.UtcNow)
;//注意sqlsugar插入时无时区直接utc时间
_config.ForType<VariableBasicData, QuestDBHistoryValue>()
//.Map(dest => dest.Id, src => CommonUtils.GetSingleId())
.Map(dest => dest.Id, src => src.Id)//Id更改为变量Id
.Map(dest => dest.Value, src => src.Value == null ? string.Empty : src.Value.ToString() ?? string.Empty)
.Map(dest => dest.CollectTime, (src) => src.CollectTime < DateTime.MinValue ? utcTime : src.CollectTime)//注意sqlsugar插入时无时区直接utc时间
.Map(dest => dest.CreateTime, (src) => DateTime.UtcNow)
;//注意sqlsugar插入时无时区直接utc时间
_config.ForType<VariableRuntime, QuestDBNumberHistoryValue>()
//.Map(dest => dest.Id, src => CommonUtils.GetSingleId())
.Map(dest => dest.Id, src => src.Id)//Id更改为变量Id
.Map(dest => dest.Value, src => src.Value.GetType() == typeof(bool) ? ConvertUtility.Convert.ToBoolean(src.Value, false) ? 1 : 0 : ConvertUtility.Convert.ToDecimal(src.Value, 0))
.Map(dest => dest.CollectTime, (src) => src.CollectTime < DateTime.MinValue ? utcTime : src.CollectTime)//注意sqlsugar插入时无时区直接utc时间
.Map(dest => dest.CreateTime, (src) => DateTime.UtcNow)
;//注意sqlsugar插入时无时区直接utc时间
_config.ForType<VariableBasicData, QuestDBNumberHistoryValue>()
//.Map(dest => dest.Id, src => CommonUtils.GetSingleId())
.Map(dest => dest.Id, src => src.Id)//Id更改为变量Id
.Map(dest => dest.Value, src => src.Value.GetType() == typeof(bool) ? ConvertUtility.Convert.ToBoolean(src.Value, false) ? 1 : 0 : ConvertUtility.Convert.ToDecimal(src.Value, 0))
.Map(dest => dest.CollectTime, (src) => src.CollectTime < DateTime.MinValue ? utcTime : src.CollectTime)//注意sqlsugar插入时无时区直接utc时间
.Map(dest => dest.CreateTime, (src) => DateTime.UtcNow)
;//注意sqlsugar插入时无时区直接utc时间
await base.InitChannelAsync(channel, cancellationToken).ConfigureAwait(false);
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using System.Diagnostics;
using ThingsGateway.Extension.Generic;
@@ -25,13 +23,12 @@ namespace ThingsGateway.Plugin.QuestDB;
/// </summary>
public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableModel<VariableBasicData>
{
private TypeAdapterConfig _config;
protected override ValueTask<OperResult> UpdateVarModel(IEnumerable<CacheDBItem<VariableBasicData>> item, CancellationToken cancellationToken)
{
return UpdateVarModel(item.Select(a => a.Value).OrderBy(a => a.Id), cancellationToken);
}
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, List<VariableBasicData> variables)
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, IEnumerable<VariableBasicData> variables)
{
TimeIntervalUpdateVariable(variables);
base.VariableTimeInterval(variableRuntimes, variables);
@@ -47,7 +44,7 @@ public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableMode
}
private void TimeIntervalUpdateVariable(List<VariableBasicData> variables)
private void TimeIntervalUpdateVariable(IEnumerable<VariableBasicData> variables)
{
if (_driverPropertys.GroupUpdate)
{
@@ -78,7 +75,7 @@ public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableMode
if (_driverPropertys.GroupUpdate && variable.BusinessGroupUpdateTrigger && !variable.BusinessGroup.IsNullOrEmpty() && VariableRuntimeGroups.TryGetValue(variable.BusinessGroup, out var variableRuntimeGroup))
{
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.Adapt<List<VariableBasicData>>(_config)));
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.AdaptListVariableBasicData()));
}
else
@@ -125,7 +122,7 @@ public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableMode
Stopwatch stopwatch = new();
stopwatch.Start();
var data = numberData.Adapt<List<QuestDBNumberHistoryValue>>(_config);
var data = numberData.AdaptListQuestDBNumberHistoryValue();
var result = await _db.Insertable(data).AS(_driverPropertys.NumberTableName).ExecuteCommandAsync(cancellationToken).ConfigureAwait(false);//不要加分表
stopwatch.Stop();
@@ -141,7 +138,7 @@ public partial class QuestDBProducer : BusinessBaseWithCacheIntervalVariableMode
{
Stopwatch stopwatch = new();
stopwatch.Start();
var data = stringData.Adapt<List<QuestDBHistoryValue>>(_config);
var data = stringData.AdaptListQuestDBHistoryValue();
var result = await _db.Insertable(data).AS(_driverPropertys.StringTableName).ExecuteCommandAsync(cancellationToken).ConfigureAwait(false);//不要加分表
stopwatch.Stop();

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.Extensions.DependencyInjection;
using System.ComponentModel.DataAnnotations;

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using ThingsGateway.Admin.Application;
using ThingsGateway.Debug;
using ThingsGateway.Foundation;
@@ -159,31 +157,6 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
{
_db = SqlDBBusinessDatabaseUtil.GetDb(_driverPropertys);
_config = new TypeAdapterConfig();
_config.ForType<VariableRuntime, SQLHistoryValue>()
//.Map(dest => dest.Id, (src) =>CommonUtils.GetSingleId())
.Map(dest => dest.Id, src => src.Id)//Id更改为变量Id
.Map(dest => dest.Value, src => src.Value == null ? string.Empty : src.Value.ToString() ?? string.Empty)
.Map(dest => dest.CreateTime, (src) => DateTime.Now);
_config.ForType<VariableBasicData, SQLHistoryValue>()
//.Map(dest => dest.Id, (src) =>CommonUtils.GetSingleId())
.Map(dest => dest.Id, src => src.Id)//Id更改为变量Id
.Map(dest => dest.Value, src => src.Value == null ? string.Empty : src.Value.ToString() ?? string.Empty)
.Map(dest => dest.CreateTime, (src) => DateTime.Now);
_config.ForType<VariableRuntime, SQLNumberHistoryValue>()
//.Map(dest => dest.Id, (src) =>CommonUtils.GetSingleId())
.Map(dest => dest.Id, src => src.Id)//Id更改为变量Id
.Map(dest => dest.Value, src => src.Value.GetType() == typeof(bool) ? ConvertUtility.Convert.ToBoolean(src.Value, false) ? 1 : 0 : ConvertUtility.Convert.ToDecimal(src.Value, 0))
.Map(dest => dest.CreateTime, (src) => DateTime.Now);
_config.ForType<VariableBasicData, SQLNumberHistoryValue>()
//.Map(dest => dest.Id, (src) =>CommonUtils.GetSingleId())
.Map(dest => dest.Id, src => src.Id)//Id更改为变量Id
.Map(dest => dest.Value, src => src.Value.GetType() == typeof(bool) ? ConvertUtility.Convert.ToBoolean(src.Value, false) ? 1 : 0 : ConvertUtility.Convert.ToDecimal(src.Value, 0))
.Map(dest => dest.CreateTime, (src) => DateTime.Now);
if (_businessPropertyWithCacheInterval.BusinessUpdateEnum == BusinessUpdateEnum.Interval && _driverPropertys.IsReadDB)
{
GlobalData.VariableValueChangeEvent += VariableValueChange;
@@ -193,6 +166,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
}
public override Task AfterVariablesChangedAsync(CancellationToken cancellationToken)
{
RealTimeVariables.Clear();

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using System.Collections.Concurrent;
using System.Diagnostics;
@@ -26,7 +24,6 @@ namespace ThingsGateway.Plugin.SqlDB;
/// </summary>
public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<VariableBasicData>
{
private TypeAdapterConfig _config;
private volatile bool _initRealData;
private ConcurrentDictionary<long, VariableBasicData> RealTimeVariables { get; } = new ConcurrentDictionary<long, VariableBasicData>();
@@ -34,7 +31,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
{
return UpdateVarModel(item.Select(a => a.Value).OrderBy(a => a.Id), cancellationToken);
}
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, List<VariableBasicData> variables)
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, IEnumerable<VariableBasicData> variables)
{
if (_driverPropertys.IsHistoryDB)
{
@@ -53,7 +50,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
return UpdateVarModel(item, cancellationToken);
}
private void TimeIntervalUpdateVariable(List<VariableBasicData> variables)
private void TimeIntervalUpdateVariable(IEnumerable<VariableBasicData> variables)
{
if (_driverPropertys.GroupUpdate)
{
@@ -85,7 +82,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
if (_driverPropertys.GroupUpdate && variable.BusinessGroupUpdateTrigger && !variable.BusinessGroup.IsNullOrEmpty() && VariableRuntimeGroups.TryGetValue(variable.BusinessGroup, out var variableRuntimeGroup))
{
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.Adapt<List<VariableBasicData>>(_config)));
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.AdaptListVariableBasicData()));
}
else
@@ -140,7 +137,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
{
Stopwatch stopwatch = new();
stopwatch.Start();
var data = numberData.Adapt<List<SQLNumberHistoryValue>>(_config);
var data = numberData.AdaptListSQLNumberHistoryValue();
var result = await _db.Fastest<SQLNumberHistoryValue>().PageSize(50000).SplitTable().BulkCopyAsync(data).ConfigureAwait(false);
stopwatch.Stop();
@@ -156,7 +153,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
{
Stopwatch stopwatch = new();
stopwatch.Start();
var data = stringData.Adapt<List<SQLHistoryValue>>(_config);
var data = stringData.AdaptListSQLHistoryValue();
var result = await _db.Fastest<SQLHistoryValue>().PageSize(50000).SplitTable().BulkCopyAsync(data).ConfigureAwait(false);
stopwatch.Stop();
@@ -202,7 +199,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
Stopwatch stopwatch = new();
stopwatch.Start();
var ids = (await _db.Queryable<SQLRealValue>().AS(_driverPropertys.ReadDBTableName).Select(a => a.Id).ToListAsync(cancellationToken).ConfigureAwait(false)).ToHashSet();
var InsertData = IdVariableRuntimes.Where(a => !ids.Contains(a.Key)).Select(a => a.Value).Adapt<List<SQLRealValue>>();
var InsertData = IdVariableRuntimes.Where(a => !ids.Contains(a.Key)).Select(a => a.Value).AdaptListSQLRealValue();
var result = await _db.Fastest<SQLRealValue>().AS(_driverPropertys.ReadDBTableName).PageSize(100000).BulkCopyAsync(InsertData).ConfigureAwait(false);
_initRealData = true;
stopwatch.Stop();
@@ -217,7 +214,7 @@ public partial class SqlDBProducer : BusinessBaseWithCacheIntervalVariableModel<
Stopwatch stopwatch = new();
stopwatch.Start();
var data = datas.Adapt<List<SQLRealValue>>(_config);
var data = datas.AdaptListSQLRealValue();
var result = await _db.Fastest<SQLRealValue>().AS(_driverPropertys.ReadDBTableName).PageSize(100000).BulkUpdateAsync(data).ConfigureAwait(false);
stopwatch.Stop();

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using ThingsGateway.Admin.Application;
using ThingsGateway.Extension.Generic;
using ThingsGateway.Foundation;
@@ -29,7 +27,6 @@ public partial class SqlHistoryAlarm : BusinessBaseWithCacheVariableModel<Histor
{
internal readonly SqlHistoryAlarmProperty _driverPropertys = new();
private readonly SqlHistoryAlarmVariableProperty _variablePropertys = new();
private TypeAdapterConfig _config = new();
public override Type DriverUIType => typeof(HistoryAlarmPage);
/// <inheritdoc/>
@@ -40,12 +37,39 @@ public partial class SqlHistoryAlarm : BusinessBaseWithCacheVariableModel<Histor
private SqlSugarClient _db;
public static HistoryAlarm AdaptHistoryAlarm(AlarmVariable src)
{
var target = new HistoryAlarm();
target.Name = src.Name;
target.Description = src.Description;
target.CreateOrgId = src.CreateOrgId;
target.CreateUserId = src.CreateUserId;
target.DeviceId = src.DeviceId;
target.DeviceName = src.DeviceName;
target.RegisterAddress = src.RegisterAddress;
target.DataType = src.DataType;
target.AlarmCode = src.AlarmCode;
target.AlarmLimit = src.AlarmLimit;
target.AlarmText = src.AlarmText;
target.RecoveryCode = src.RecoveryCode;
target.AlarmTime = src.AlarmTime;
target.EventTime = src.EventTime;
target.AlarmType = src.AlarmType;
target.EventType = src.EventType;
target.Remark1 = src.Remark1;
target.Remark2 = src.Remark2;
target.Remark3 = src.Remark3;
target.Remark4 = src.Remark4;
target.Remark5 = src.Remark5;
target.Id = CommonUtils.GetSingleId();
return target;
}
protected override async Task InitChannelAsync(IChannel? channel, CancellationToken cancellationToken)
{
_db = BusinessDatabaseUtil.GetDb((DbType)_driverPropertys.DbType, _driverPropertys.BigTextConnectStr);
_config.ForType<AlarmVariable, HistoryAlarm>().Map(dest => dest.Id, (src) => CommonUtils.GetSingleId());
GlobalData.AlarmChangedEvent -= AlarmWorker_OnAlarmChanged;
GlobalData.ReadOnlyRealAlarmIdVariables?.ForEach(a =>
{

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using System.Diagnostics;
using ThingsGateway.Foundation;
@@ -38,7 +36,7 @@ public partial class SqlHistoryAlarm : BusinessBaseWithCacheVariableModel<Histor
{
if (CurrentDevice.Pause)
return;
AddQueueVarModel(new CacheDBItem<HistoryAlarm>(alarmVariable.Adapt<HistoryAlarm>(_config)));
AddQueueVarModel(new CacheDBItem<HistoryAlarm>(AdaptHistoryAlarm(alarmVariable)));
}
public override void PauseThread(bool pause)
{

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using System.Reflection;
using ThingsGateway.Admin.Application;
@@ -86,17 +84,7 @@ public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariableM
assemblies.Add(typeof(TDengineProvider).Assembly);
InstanceFactory.CustomAssemblies = assemblies.ToArray();
_config = new TypeAdapterConfig();
_config.ForType<VariableRuntime, TDengineDBNumberHistoryValue>()
.Map(dest => dest.Value, src => ConvertUtility.Convert.ToDecimal(src.Value, 0))
//.Map(dest => dest.Id, src => CommonUtils.GetSingleId())
.Map(dest => dest.Id, src => src.Id)//Id更改为变量Id
;//注意sqlsugar插入时无时区直接utc时间
_config.ForType<VariableBasicData, TDengineDBNumberHistoryValue>()
.Map(dest => dest.Value, src => ConvertUtility.Convert.ToDecimal(src.Value, 0))
//.Map(dest => dest.Id, src => CommonUtils.GetSingleId())
.Map(dest => dest.Id, src => src.Id)//Id更改为变量Id
;//注意sqlsugar插入时无时区直接utc时间
await base.InitChannelAsync(channel, cancellationToken).ConfigureAwait(false);
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Newtonsoft.Json.Linq;
using System.Diagnostics;
@@ -30,14 +28,13 @@ namespace ThingsGateway.Plugin.TDengineDB;
/// </summary>
public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariableModel<VariableBasicData>
{
private TypeAdapterConfig _config;
protected override ValueTask<OperResult> UpdateVarModel(IEnumerable<CacheDBItem<VariableBasicData>> item, CancellationToken cancellationToken)
{
return UpdateVarModel(item.Select(a => a.Value).OrderBy(a => a.Id), cancellationToken);
}
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, List<VariableBasicData> variables)
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, IEnumerable<VariableBasicData> variables)
{
TimeIntervalUpdateVariable(variables);
base.VariableTimeInterval(variableRuntimes, variables);
@@ -52,7 +49,7 @@ public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariableM
{
return UpdateVarModel(item, cancellationToken);
}
private void TimeIntervalUpdateVariable(List<VariableBasicData> variables)
private void TimeIntervalUpdateVariable(IEnumerable<VariableBasicData> variables)
{
if (_driverPropertys.GroupUpdate)
{
@@ -82,7 +79,7 @@ public partial class TDengineDBProducer : BusinessBaseWithCacheIntervalVariableM
if (_driverPropertys.GroupUpdate && variable.BusinessGroupUpdateTrigger && !variable.BusinessGroup.IsNullOrEmpty() && VariableRuntimeGroups.TryGetValue(variable.BusinessGroup, out var variableRuntimeGroup))
{
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.Adapt<List<VariableBasicData>>(_config)));
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.AdaptListVariableBasicData()));
}
else

View File

@@ -10,8 +10,6 @@
using BootstrapBlazor.Components;
using Mapster;
using ThingsGateway.Extension.Generic;
using ThingsGateway.Foundation;
@@ -74,7 +72,7 @@ public partial class Webhook : BusinessBaseWithCacheIntervalScript<VariableBasic
return UpdateVarModel(item, cancellationToken);
}
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, List<VariableBasicData> variables)
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, IEnumerable<VariableBasicData> variables)
{
TimeIntervalUpdateVariable(variables);
base.VariableTimeInterval(variableRuntimes, variables);
@@ -85,7 +83,7 @@ public partial class Webhook : BusinessBaseWithCacheIntervalScript<VariableBasic
base.VariableChange(variableRuntime, variable);
}
private void TimeIntervalUpdateVariable(List<VariableBasicData> variables)
private void TimeIntervalUpdateVariable(IEnumerable<VariableBasicData> variables)
{
if (!_businessPropertyWithCacheIntervalScript.VariableTopic.IsNullOrWhiteSpace())
{
@@ -121,7 +119,7 @@ public partial class Webhook : BusinessBaseWithCacheIntervalScript<VariableBasic
if (_driverPropertys.GroupUpdate && variable.BusinessGroupUpdateTrigger && !variable.BusinessGroup.IsNullOrEmpty() && VariableRuntimeGroups.TryGetValue(variable.BusinessGroup, out var variableRuntimeGroup))
{
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.Adapt<List<VariableBasicData>>()));
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.AdaptListVariableBasicData()));
}
else

View File

@@ -10,8 +10,6 @@
using Confluent.Kafka;
using Mapster;
using ThingsGateway.Extension.Generic;
using ThingsGateway.Foundation;
using ThingsGateway.Foundation.Extension.Generic;
@@ -70,7 +68,7 @@ public partial class KafkaProducer : BusinessBaseWithCacheIntervalScript<Variabl
return UpdateVarModel(item, cancellationToken);
}
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, List<VariableBasicData> variables)
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, IEnumerable<VariableBasicData> variables)
{
TimeIntervalUpdateVariable(variables);
base.VariableTimeInterval(variableRuntimes, variables);
@@ -80,7 +78,7 @@ public partial class KafkaProducer : BusinessBaseWithCacheIntervalScript<Variabl
UpdateVariable(variableRuntime, variable);
base.VariableChange(variableRuntime, variable);
}
private void TimeIntervalUpdateVariable(List<VariableBasicData> variables)
private void TimeIntervalUpdateVariable(IEnumerable<VariableBasicData> variables)
{
if (!_businessPropertyWithCacheIntervalScript.VariableTopic.IsNullOrWhiteSpace())
{
@@ -91,7 +89,7 @@ public partial class KafkaProducer : BusinessBaseWithCacheIntervalScript<Variabl
foreach (var group in varGroup)
{
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(group.Adapt<List<VariableBasicData>>()));
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(group.AdaptIEnumerableVariableBasicData()));
}
foreach (var variable in varList)
{
@@ -115,7 +113,7 @@ public partial class KafkaProducer : BusinessBaseWithCacheIntervalScript<Variabl
if (_driverPropertys.GroupUpdate && variable.BusinessGroupUpdateTrigger && !variable.BusinessGroup.IsNullOrEmpty() && VariableRuntimeGroups.TryGetValue(variable.BusinessGroup, out var variableRuntimeGroup))
{
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.Adapt<List<VariableBasicData>>()));
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.AdaptListVariableBasicData()));
}
else
@@ -175,9 +173,9 @@ public partial class KafkaProducer : BusinessBaseWithCacheIntervalScript<Variabl
{
//保留消息
//分解List避免超出字节大小限制
var varData = IdVariableRuntimes.Select(a => a.Value).Adapt<List<VariableBasicData>>().ChunkBetter(_driverPropertys.SplitSize);
var devData = CollectDevices?.Select(a => a.Value).Adapt<List<DeviceBasicData>>().ChunkBetter(_driverPropertys.SplitSize);
var alramData = GlobalData.ReadOnlyRealAlarmIdVariables.Select(a => a.Value).Adapt<List<AlarmVariable>>().ChunkBetter(_driverPropertys.SplitSize);
var varData = IdVariableRuntimes.Select(a => a.Value).AdaptIEnumerableVariableBasicData().ChunkBetter(_driverPropertys.SplitSize);
var devData = CollectDevices?.Select(a => a.Value).AdaptListDeviceBasicData().ChunkBetter(_driverPropertys.SplitSize);
var alramData = GlobalData.ReadOnlyRealAlarmIdVariables.Select(a => a.Value).ChunkBetter(_driverPropertys.SplitSize);
foreach (var item in varData)
{
if (!success)

View File

@@ -12,8 +12,6 @@ using BootstrapBlazor.Components;
using CSScripting;
using Mapster;
using MQTTnet;
@@ -128,7 +126,7 @@ public partial class MqttClient : BusinessBaseWithCacheIntervalScript<VariableBa
}
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, List<VariableBasicData> variables)
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, IEnumerable<VariableBasicData> variables)
{
TimeIntervalUpdateVariable(variables);
base.VariableTimeInterval(variableRuntimes, variables);
@@ -138,7 +136,7 @@ public partial class MqttClient : BusinessBaseWithCacheIntervalScript<VariableBa
UpdateVariable(variableRuntime, variable);
base.VariableChange(variableRuntime, variable);
}
private void TimeIntervalUpdateVariable(List<VariableBasicData> variables)
private void TimeIntervalUpdateVariable(IEnumerable<VariableBasicData> variables)
{
if (!_businessPropertyWithCacheIntervalScript.VariableTopic.IsNullOrWhiteSpace())
{
@@ -149,7 +147,7 @@ public partial class MqttClient : BusinessBaseWithCacheIntervalScript<VariableBa
foreach (var group in varGroup)
{
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(group.Adapt<List<VariableBasicData>>()));
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(group.AdaptIEnumerableVariableBasicData()));
}
foreach (var variable in varList)
{
@@ -173,7 +171,7 @@ public partial class MqttClient : BusinessBaseWithCacheIntervalScript<VariableBa
if (_driverPropertys.GroupUpdate && variable.BusinessGroupUpdateTrigger && !variable.BusinessGroup.IsNullOrEmpty() && VariableRuntimeGroups.TryGetValue(variable.BusinessGroup, out var variableRuntimeGroup))
{
//获取组内全部变量
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.Adapt<List<VariableBasicData>>()));
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.AdaptListVariableBasicData()));
}
else
{
@@ -255,9 +253,9 @@ public partial class MqttClient : BusinessBaseWithCacheIntervalScript<VariableBa
{
//保留消息
//分解List避免超出mqtt字节大小限制
var varData = IdVariableRuntimes.Select(a => a.Value).Adapt<List<VariableBasicData>>().ChunkBetter(_driverPropertys.SplitSize);
var devData = CollectDevices?.Select(a => a.Value).Adapt<List<DeviceBasicData>>().ChunkBetter(_driverPropertys.SplitSize);
var alramData = GlobalData.ReadOnlyRealAlarmIdVariables.Select(a => a.Value).Adapt<List<AlarmVariable>>().ChunkBetter(_driverPropertys.SplitSize);
var varData = IdVariableRuntimes.Select(a => a.Value).AdaptIEnumerableVariableBasicData().ChunkBetter(_driverPropertys.SplitSize);
var devData = CollectDevices?.Select(a => a.Value).AdaptListDeviceBasicData().ChunkBetter(_driverPropertys.SplitSize);
var alramData = GlobalData.ReadOnlyRealAlarmIdVariables.Select(a => a.Value).ChunkBetter(_driverPropertys.SplitSize);
foreach (var item in varData)
{
if (!success)

View File

@@ -10,8 +10,6 @@
using CSScripting;
using Mapster;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
@@ -84,7 +82,7 @@ public partial class MqttServer : BusinessBaseWithCacheIntervalScript<VariableBa
{
return UpdateVarModel(item, cancellationToken);
}
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, List<VariableBasicData> variables)
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, IEnumerable<VariableBasicData> variables)
{
TimeIntervalUpdateVariable(variables);
base.VariableTimeInterval(variableRuntimes, variables);
@@ -94,7 +92,7 @@ public partial class MqttServer : BusinessBaseWithCacheIntervalScript<VariableBa
UpdateVariable(variableRuntime, variable);
base.VariableChange(variableRuntime, variable);
}
private void TimeIntervalUpdateVariable(List<VariableBasicData> variables)
private void TimeIntervalUpdateVariable(IEnumerable<VariableBasicData> variables)
{
if (!_businessPropertyWithCacheIntervalScript.VariableTopic.IsNullOrWhiteSpace())
{
@@ -105,7 +103,7 @@ public partial class MqttServer : BusinessBaseWithCacheIntervalScript<VariableBa
foreach (var group in varGroup)
{
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(group.Adapt<List<VariableBasicData>>()));
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(group.AdaptIEnumerableVariableBasicData()));
}
foreach (var variable in varList)
{
@@ -131,7 +129,7 @@ public partial class MqttServer : BusinessBaseWithCacheIntervalScript<VariableBa
//获取组内全部变量
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.Adapt<List<VariableBasicData>>()));
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.AdaptListVariableBasicData()));
}
else
@@ -253,9 +251,9 @@ public partial class MqttServer : BusinessBaseWithCacheIntervalScript<VariableBa
{
//首次连接时的保留消息
//分解List避免超出mqtt字节大小限制
var varData = IdVariableRuntimes.Select(a => a.Value).Adapt<List<VariableBasicData>>().ChunkBetter(_driverPropertys.SplitSize);
var devData = CollectDevices?.Select(a => a.Value).Adapt<List<DeviceBasicData>>().ChunkBetter(_driverPropertys.SplitSize);
var alramData = GlobalData.ReadOnlyRealAlarmIdVariables.Select(a => a.Value).Adapt<List<AlarmVariable>>().ChunkBetter(_driverPropertys.SplitSize);
var varData = IdVariableRuntimes.Select(a => a.Value).AdaptIEnumerableVariableBasicData().ChunkBetter(_driverPropertys.SplitSize);
var devData = CollectDevices?.Select(a => a.Value).AdaptListDeviceBasicData().ChunkBetter(_driverPropertys.SplitSize);
var alramData = GlobalData.ReadOnlyRealAlarmIdVariables.Select(a => a.Value).ChunkBetter(_driverPropertys.SplitSize);
List<MqttApplicationMessage> Messages = new();
if (!_businessPropertyWithCacheIntervalScript.VariableTopic.IsNullOrEmpty())

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Newtonsoft.Json.Linq;
using Opc.Ua;
@@ -32,7 +30,6 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
{
private const string ReferenceServer = "https://thingsgateway.cn/";
private readonly TypeAdapterConfig _config;
/// <summary>
/// OPC和网关对应表
/// </summary>
@@ -45,14 +42,25 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
public ThingsGatewayNodeManager(BusinessBase businessBase, IServerInternal server, ApplicationConfiguration configuration) : base(server, configuration, ReferenceServer)
{
_businessBase = businessBase;
_config = new TypeAdapterConfig();
_config.ForType<IDBHistoryValue, DataValue>()
.Map(dest => dest.WrappedValue, (src) => new Variant(src.Value))
.Map(dest => dest.SourceTimestamp, src => DateTime.SpecifyKind(src.CollectTime, DateTimeKind.Local))
.Map(dest => dest.ServerTimestamp, src => DateTime.SpecifyKind(src.CreateTime, DateTimeKind.Local))
.Map(dest => dest.StatusCode, (src) =>
src.IsOnline ? StatusCodes.Good : StatusCodes.Bad);
}
public DataValue AdaptDataValue(IDBHistoryValue src)
{
var dest = new DataValue();
dest.WrappedValue = new Variant(src.Value);
dest.SourceTimestamp = DateTime.SpecifyKind(src.CollectTime, DateTimeKind.Local);
dest.ServerTimestamp = DateTime.SpecifyKind(src.CreateTime, DateTimeKind.Local);
dest.StatusCode = src.IsOnline ? StatusCodes.Good : StatusCodes.Bad;
dest.Value = src.Value;
return dest;
}
public List<DataValue> AdaptListDataValue(IEnumerable<IDBHistoryValue> src)
{
return Enumerable.ToList(
Enumerable.Select(src, x => AdaptDataValue(x))
);
}
ConcurrentList<IDriver>? dbDrivers;
internal FolderState rootFolder;
@@ -182,7 +190,7 @@ public class ThingsGatewayNodeManager : CustomNodeManager2
if (data.Count > 0)
{
var hisDataValue = data.Adapt<List<DataValue>>(_config);
var hisDataValue = AdaptListDataValue(data);
HistoryData hisData = new();
hisData.DataValues.AddRange(hisDataValue);
errors[i] = StatusCodes.Good;

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
@@ -82,7 +80,7 @@ public partial class OpcUaServer : BusinessBase
IdVariableRuntimes.ForEach(a =>
{
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
VariableValueChange(a.Value, a.Value.AdaptVariableBasicData());
});
@@ -166,7 +164,7 @@ public partial class OpcUaServer : BusinessBase
connect_success = true;
IdVariableRuntimes.ForEach(a =>
{
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
VariableValueChange(a.Value, a.Value.AdaptVariableBasicData());
});
}
catch (Exception ex)
@@ -428,7 +426,7 @@ public partial class OpcUaServer : BusinessBase
{
IdVariableRuntimes.ForEach(a =>
{
VariableValueChange(a.Value, a.Value.Adapt<VariableBasicData>());
VariableValueChange(a.Value, a.Value.AdaptVariableBasicData());
});
}
}

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using RabbitMQ.Client;
using ThingsGateway.Extension.Generic;
@@ -71,7 +69,7 @@ public partial class RabbitMQProducer : BusinessBaseWithCacheIntervalScript<Vari
return UpdateVarModel(item, cancellationToken);
}
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, List<VariableBasicData> variables)
protected override void VariableTimeInterval(IEnumerable<VariableRuntime> variableRuntimes, IEnumerable<VariableBasicData> variables)
{
TimeIntervalUpdateVariable(variables);
base.VariableTimeInterval(variableRuntimes, variables);
@@ -81,7 +79,7 @@ public partial class RabbitMQProducer : BusinessBaseWithCacheIntervalScript<Vari
UpdateVariable(variableRuntime, variable);
base.VariableChange(variableRuntime, variable);
}
private void TimeIntervalUpdateVariable(List<VariableBasicData> variables)
private void TimeIntervalUpdateVariable(IEnumerable<VariableBasicData> variables)
{
if (!_businessPropertyWithCacheIntervalScript.VariableTopic.IsNullOrWhiteSpace())
{
@@ -92,7 +90,7 @@ public partial class RabbitMQProducer : BusinessBaseWithCacheIntervalScript<Vari
foreach (var group in varGroup)
{
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(group.Adapt<List<VariableBasicData>>()));
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(group.AdaptIEnumerableVariableBasicData()));
}
foreach (var variable in varList)
{
@@ -117,7 +115,7 @@ public partial class RabbitMQProducer : BusinessBaseWithCacheIntervalScript<Vari
{
//获取组内全部变量
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.Adapt<List<VariableBasicData>>()));
AddQueueVarModel(new CacheDBItem<List<VariableBasicData>>(variableRuntimeGroup.AdaptListVariableBasicData()));
}
else
@@ -177,9 +175,9 @@ public partial class RabbitMQProducer : BusinessBaseWithCacheIntervalScript<Vari
{
//保留消息
//分解List避免超出字节大小限制
var varData = IdVariableRuntimes.Select(a => a.Value).Adapt<List<VariableBasicData>>().ChunkBetter(_driverPropertys.SplitSize);
var devData = CollectDevices?.Select(a => a.Value).Adapt<List<DeviceBasicData>>().ChunkBetter(_driverPropertys.SplitSize);
var alramData = GlobalData.ReadOnlyRealAlarmIdVariables.Select(a => a.Value).Adapt<List<AlarmVariable>>().ChunkBetter(_driverPropertys.SplitSize);
var varData = IdVariableRuntimes.Select(a => a.Value).AdaptIEnumerableVariableBasicData().ChunkBetter(_driverPropertys.SplitSize);
var devData = CollectDevices?.Select(a => a.Value).AdaptListDeviceBasicData().ChunkBetter(_driverPropertys.SplitSize);
var alramData = GlobalData.ReadOnlyRealAlarmIdVariables.Select(a => a.Value).ChunkBetter(_driverPropertys.SplitSize);
foreach (var item in varData)
{
if (!success)

View File

@@ -8,8 +8,6 @@
// QQ群605534569
//------------------------------------------------------------------------------
using Mapster;
using Newtonsoft.Json.Linq;
using ThingsGateway.Admin.Application;
@@ -92,7 +90,7 @@ public partial class Synchronization : BusinessBase, IRpcDriver
// 如果 online 为 true表示设备在线
if (online)
{
var deviceRunTimes = CollectDevices.Where(a => a.Value.IsCollect == true).Select(a => a.Value).Adapt<List<DeviceDataWithValue>>();
var deviceRunTimes = CollectDevices.Where(a => a.Value.IsCollect == true).Select(a => a.Value).AdaptDeviceDataWithValue();
foreach (var item in _tcpDmtpService.Clients)
{
@@ -129,7 +127,7 @@ public partial class Synchronization : BusinessBase, IRpcDriver
// 如果 online 为 true表示设备在线
if (online)
{
var deviceRunTimes = CollectDevices.Where(a => a.Value.IsCollect == true).Select(a => a.Value).Adapt<List<DeviceDataWithValue>>();
var deviceRunTimes = CollectDevices.Where(a => a.Value.IsCollect == true).Select(a => a.Value).AdaptDeviceDataWithValue();
// 将 GlobalData.CollectDevices 和 GlobalData.Variables 同步到从站
await _tcpDmtpClient.GetDmtpRpcActor().InvokeAsync(

View File

@@ -11,8 +11,6 @@
#pragma warning disable CA2007 // 考虑对等待的任务调用 ConfigureAwait
using BootstrapBlazor.Components;
using Mapster;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.Extensions.Localization;
@@ -95,7 +93,7 @@ public partial class Login
}
else
{
var model = loginModel.Adapt<LoginInput>();
var model = loginModel.AdaptLoginInput();
model.Password = DESEncryption.Encrypt(model.Password);
try

View File

@@ -39,7 +39,6 @@ public class Startup : AppStartup
{
public void ConfigBlazorServer(IServiceCollection services)
{
// 增加中文编码支持网页源码显示汉字
services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.All));
//并发启动/停止host

View File

@@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
//------------------------------------------------------------------------------
using Riok.Mapperly.Abstractions;
using TouchSocket.Dmtp;
namespace ThingsGateway.Upgrade;
[Mapper(UseDeepCloning = true, EnumMappingStrategy = EnumMappingStrategy.ByName, RequiredMappingStrategy = RequiredMappingStrategy.None)]
public static partial class UpgradeMapper
{
public static partial List<TcpSessionClientDto> AdaptListTcpSessionClientDto(this List<TcpDmtpSessionClient> src);
}

View File

@@ -9,8 +9,6 @@
//------------------------------------------------------------------------------
#pragma warning disable CA2007 // 考虑对等待的任务调用 ConfigureAwait
using Mapster;
using ThingsGateway.Admin.Application;
using TouchSocket.Dmtp;
@@ -65,7 +63,7 @@ public partial class GatewayOnlinePage
if (TcpDmtpService != null)
{
var clients = TcpDmtpService.Clients.ToList();
var data = clients.Adapt<List<TcpSessionClientDto>>();
var data = clients.AdaptListTcpSessionClientDto();
var query = data.GetQueryData(options);

View File

@@ -17,12 +17,13 @@
<ItemGroup>
<PackageReference Include="TouchSocket.Dmtp" Version="3.1.11" />
<PackageReference Include="Riok.Mapperly" Version="4.2.1" ExcludeAssets="runtime" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Admin\ThingsGateway.Admin.Razor\ThingsGateway.Admin.Razor.csproj" />
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Razor\ThingsGateway.Foundation.Razor.csproj" />
<ProjectReference Include="..\..\Admin\ThingsGateway.Admin.Razor\ThingsGateway.Admin.Razor.csproj" />
<ProjectReference Include="..\..\Foundation\ThingsGateway.Foundation.Razor\ThingsGateway.Foundation.Razor.csproj" />
</ItemGroup>

View File

@@ -1,5 +1,3 @@
global using Mapster;
global using ThingsGateway.Admin.Application;
global using ThingsGateway.Admin.Application;
global using ThingsGateway.Admin.Razor;
global using ThingsGateway.Razor;

View File

@@ -67,7 +67,7 @@ public partial class Login
private async Task LoginAsync(EditContext context)
{
var model = loginModel.Adapt<LoginInput>();
var model = loginModel.AdaptLoginInput();
model.Password = DESEncryption.Encrypt(model.Password);
try

View File

@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>10.9.3</Version>
<Version>10.9.4</Version>
</PropertyGroup>
<ItemGroup>