Files
ThingsGateway/src/Gateway/ThingsGateway.Gateway.Application/Driver/DynamicModelExtension.cs
2248356998 qq.com cf6e8b58f0 更新内存变量
2025-09-23 01:22:02 +08:00

153 lines
6.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
// ------------------------------------------------------------------------------
using System.Reflection;
using ThingsGateway.Common.Extension.Generic;
using ThingsGateway.NewLife.Extension;
using ThingsGateway.NewLife.Json.Extension;
using ThingsGateway.NewLife.Reflection;
namespace ThingsGateway.Gateway.Application;
[ThingsGateway.DependencyInjection.SuppressSniffer]
public static class DynamicModelExtension
{
/// <summary>
/// GetDynamicModel
/// </summary>
public static IEnumerable<object> GetDynamicModel<T>(this IEnumerable<T> datas, string script, TouchSocket.Core.ILog log)
{
if (!string.IsNullOrEmpty(script))
{
//执行脚本,获取新实体
var getDeviceModel = CSharpScriptEngineExtension.Do<IDynamicModel>(script);
if (getDeviceModel is DynamicModelBase dynamicModelBase)
{
dynamicModelBase.Logger = log;
}
return getDeviceModel.GetList(datas?.Cast<object>());
}
else
{
return datas?.Cast<object>();
}
}
#if !Management
/// <summary>
/// 获取变量的业务属性值
/// </summary>
/// <param name="variableRuntime">当前变量</param>
/// <param name="businessId">对应业务设备Id</param>
/// <param name="propertyName">属性名称</param>
/// <returns>属性值如果不存在则返回null</returns>
public static string? GetPropertyValue(this VariableRuntime variableRuntime, long businessId, string propertyName)
{
if (variableRuntime == null || propertyName.IsNullOrWhiteSpace())
return null;
// 检查是否存在对应的业务设备Id
if (variableRuntime.VariablePropertys?.TryGetValue(businessId, out var keyValuePairs) == true)
{
keyValuePairs.TryGetValue(propertyName, out var value);
return value; // 返回属性值
}
if (GlobalData.IdDevices.TryGetValue(businessId, out var deviceRuntime))
{
if (deviceRuntime.Driver is BusinessBase businessBase)
{
if (businessBase.DriverProperties is IBusinessPropertyAllVariableBase property && property.IsAllVariable)
{
if (variableRuntime.IsInternalMemoryVariable == false)
return GetVariableProperty(variableRuntime, businessId, propertyName, businessBase);
}
else if (businessBase.RefreshRuntimeAlways)
{
return GetVariableProperty(variableRuntime, businessId, propertyName, businessBase);
}
}
}
return null; // 未找到对应的业务设备Id返回null
static string? GetVariableProperty(VariableRuntime variableRuntime, long businessId, string propertyName, BusinessBase businessBase)
{
// 检查是否存在对应的业务设备Id
if (variableRuntime.VariablePropertys?.TryGetValue(businessId, out var kv) == true)
{
kv.TryGetValue(propertyName, out var value);
return value; // 返回属性值
}
else
{
return ThingsGatewayStringConverter.Default.Serialize(null, businessBase.VariablePropertys.GetValue(propertyName, false));
}
}
}
#endif
public static IEnumerable<IGrouping<object[], T>> GroupByKeys<T>(this IEnumerable<T> values, params string[] keys)
{
// 获取动态对象集合中指定键的属性信息
var properties = GetProperties(values, keys);
// 使用对象数组作为键进行分组
return values.GroupBy(v => properties.Select(property => property.GetValue(v)).ToArray(), new ArrayEqualityComparer());
}
private static PropertyInfo[] GetProperties<T>(this IEnumerable<T> value, params string[] names)
{
// 获取动态对象集合的类型
var type = value.GetType().GetGenericArguments().FirstOrDefault() ?? throw new ArgumentNullException(nameof(value));
var namesStr = names.ToSystemTextJsonString(false);
// 构建缓存键,包括属性名和类型信息
var cacheKey = $"{nameof(GetProperties)}-{namesStr}-{type.FullName}-{type.TypeHandle.Value}";
// 从缓存中获取属性信息,如果缓存不存在,则创建并缓存
var result = App.CacheService.GetOrAdd(cacheKey, a =>
{
// 获取动态对象类型中指定名称的属性信息
var allProperties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty)
.ToDictionary(pi => pi.Name, pi => pi);
// 检查是否找到了所有指定名称的属性,如果没有找到,则抛出异常
var properties = names.Select(name =>
{
if (!allProperties.TryGetValue(name, out var pi))
throw new InvalidOperationException($"Couldn't find property '{name}' on type: {type.Name}");
return pi;
}).ToArray();
return properties; // 返回属性信息集合
}, 3600); // 缓存有效期为3600秒
return result; // 返回属性信息集合
}
}
public interface IDynamicModel
{
IEnumerable<dynamic> GetList(IEnumerable<object> datas);
}
public abstract class DynamicModelBase : IDynamicModel
{
public TouchSocket.Core.ILog Logger { get; set; }
public abstract IEnumerable<dynamic> GetList(IEnumerable<object> datas);
}