OpenRobot.Framework.DynamicGeneralService
1.1.1
dotnet add package OpenRobot.Framework.DynamicGeneralService --version 1.1.1
NuGet\Install-Package OpenRobot.Framework.DynamicGeneralService -Version 1.1.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="OpenRobot.Framework.DynamicGeneralService" Version="1.1.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="OpenRobot.Framework.DynamicGeneralService" Version="1.1.1" />
<PackageReference Include="OpenRobot.Framework.DynamicGeneralService" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add OpenRobot.Framework.DynamicGeneralService --version 1.1.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: OpenRobot.Framework.DynamicGeneralService, 1.1.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package OpenRobot.Framework.DynamicGeneralService@1.1.1
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=OpenRobot.Framework.DynamicGeneralService&version=1.1.1
#tool nuget:?package=OpenRobot.Framework.DynamicGeneralService&version=1.1.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
OpenRobot.Framework.DynamicGeneralService
一个强大的 .NET 8.0 动态属性管理服务库,为处理动态属性场景(如设备配置、结构化参数等)提供一站式解决方案。该库与 OpenRobot.Framework.DynamicModel 紧密配合,实现了动态属性的 CRUD 操作、实体与 DTO 之间的双向转换、以及嵌套属性树管理。
主要特性
- 动态属性管理 - 支持运行时动态创建和管理属性结构
- 嵌套属性支持 - 完整支持点号分隔的嵌套属性路径(如 "Structure.Servos.Axis1.Name")
- 数组节点管理 - 内置数组属性的创建、删除和索引管理
- 双向转换 - 实体与 DTO 之间的无缝转换
- 批量更新 - 高效的批量属性值更新
- ABP 框架集成 - 基于 ABP 框架的仓储模式,支持依赖注入
安装
dotnet add package OpenRobot.Framework.DynamicGeneralService
或在 Visual Studio 的 NuGet 包管理器控制台中运行:
Install-Package OpenRobot.Framework.DynamicGeneralService
快速开始
1. 定义动态属性实体
using Abp.Domain.Entities;
using OpenRobot.Framework.DynamicModel;
public class MyPropEntity : Entity, IDynamicPropEntity
{
public int DynamicPropertyId { get; set; }
public string PropertyName { get; set; }
public string TypeName { get; set; }
public string AttrName { get; set; }
public bool IsBaseType { get; set; }
public bool IsArray { get; set; }
public int Index { get; set; }
public string Value { get; set; }
public string ParentID { get; set; }
public string Title { get; set; }
public string Regex { get; set; }
public string ErrorMessage { get; set; }
public DateTime LastUpdateTime { get; set; }
}
2. 创建服务实例
using OpenRobot.Framework.DynamicGeneralService;
public class MyApplicationService : ITransientDependency
{
private readonly GeneralPropService<MyPropEntity, int> _generalPropService;
private readonly IRepository<MyPropEntity, int> _repository;
public MyApplicationService(IRepository<MyPropEntity, int> repository)
{
_repository = repository;
_generalPropService = new GeneralPropService<MyPropEntity, int>(repository);
}
}
使用示例
创建嵌套数组属性
// 定义模板 DTO
public class ServoAxisTemplate : IDynamicTemplateDto
{
[Description("轴名称")]
public string Name { get; set; }
[Description("最大速度")]
public int MaxSpeed { get; set; }
[Description("使能状态")]
public bool Enabled { get; set; }
}
// 创建多个伺服轴配置
var createServoDto = new CreateServoAxisDto
{
DeviceTypeId = 123,
Items = new List<ServoAxisTemplate>
{
new ServoAxisTemplate { Name = "X轴", MaxSpeed = 1000, Enabled = true },
new ServoAxisTemplate { Name = "Y轴", MaxSpeed = 800, Enabled = true },
new ServoAxisTemplate { Name = "Z轴", MaxSpeed = 500, Enabled = false }
}
};
// 构建动态属性实体列表
var propEntities = await _generalPropService.GetBuildPropList(
"Structure.Servos", // 父属性标签
createServoDto.DeviceTypeId, // 父实体 ID
() => createServoDto.Items // DTO 列表提供函数
);
// 批量插入到数据库
await _repository.InsertManyAsync(propEntities);
批量更新属性值
var updateDto = new GeneralPropUpdateDto
{
Items = new List<UpdatePropItemDto>
{
new UpdatePropItemDto { Id = 1, PropName = "Name", PropValue = "新名称" },
new UpdatePropItemDto { Id = 2, PropName = "MaxSpeed", PropValue = "1200" },
new UpdatePropItemDto { Id = 3, PropName = "Enabled", PropValue = "false" }
}
};
await _generalPropService.UpdateAsync(updateDto);
删除数组节点
// 删除指定叶子节点及其所有子属性
// 例如:删除 "Y轴" 及其所有子属性
await _generalPropService.DeleteArrayNodeByLeafId(leafId: 456);
查询并转换为 DTO
// 定义结果 DTO
public class ServoConfigDto : ICustomPropConvert
{
public string Name { get; set; }
public int MaxSpeed { get; set; }
public bool Enabled { get; set; }
public void OpenDynamicPropertryBuild(List<OpenModel> openModels)
{
foreach (var model in openModels)
{
switch (model.PropertyName)
{
case "Name":
Name = model.Value;
break;
case "MaxSpeed":
MaxSpeed = int.Parse(model.Value);
break;
case "Enabled":
Enabled = bool.Parse(model.Value);
break;
}
}
}
}
// 方式一:从数据库查询并转换单个 DTO
var dto = await _generalPropService.ConvertToSingleDto<ServoConfigDto>(
x => x.DynamicPropertyId == 123 && x.PropertyName.StartsWith("Structure.Servos")
);
// 方式二:从已有实体列表转换
var dto = _generalPropService.ConvertToSingleDto<ServoConfigDto>(propList);
查询并转换为 DTO 列表
var mainIds = new List<int> { 123, 124, 125 };
var dtoList = await _generalPropService.ConvertToListDto<ServoConfigDto>(
x => mainIds.Contains(x.DynamicPropertyId),
mainIds
);
实体与 OpenModel 之间的转换
// 实体列表转 OpenModel 列表
var openModels = _generalPropService.ListEntityToListOpenModel(entityList);
// OpenModel 列表转实体列表
var entities = _generalPropService.ListOpenModelToListEntity(openModels);
完整示例:设备配置管理
using Abp.Domain.Repositories;
using Abp.Dependency;
using OpenRobot.Framework.DynamicGeneralService;
using OpenRobot.Framework.DynamicModel;
using Abp.UI;
public class DeviceConfigService : ITransientDependency
{
private readonly IRepository<DeviceConfigPropEntity, int> _repository;
private readonly GeneralPropService<DeviceConfigPropEntity, int> _generalPropService;
public DeviceConfigService(
IRepository<DeviceConfigPropEntity, int> repository)
{
_repository = repository;
_generalPropService = new GeneralPropService<DeviceConfigPropEntity, int>(repository);
}
/// <summary>
/// 创建伺服轴配置
/// </summary>
public async Task CreateServoAxis(CreateServoAxisDto createServo)
{
var propEntities = await _generalPropService.GetBuildPropList(
"Structure.Servos",
createServo.DeviceTypeId,
() => createServo.Items
);
if (propEntities.Count == 0)
{
throw new UserFriendlyException("操作成功,未创建有效数据!");
}
await _repository.InsertManyAsync(propEntities);
}
/// <summary>
/// 创建主轴配置
/// </summary>
public async Task CreateSpindleAxis(CreateSpindleAxisDto createSpindle)
{
var propEntities = await _generalPropService.GetBuildPropList(
"Structure.Spindles",
createSpindle.DeviceTypeId,
() => createSpindle.Items
);
if (propEntities.Count == 0)
{
throw new UserFriendlyException("操作成功,未创建有效数据!");
}
await _repository.InsertManyAsync(propEntities);
}
/// <summary>
/// 获取设备结构配置
/// </summary>
public async Task<StructureConfigDto> GetStructureConfig(int deviceId)
{
var queryable = await _repository.GetQueryableAsync();
var propList = await queryable
.AsNoTracking()
.Where(d => d.DynamicPropertyId == deviceId &&
d.PropertyName.StartsWith("Structure."))
.ToListAsync();
if (propList.Count == 0)
{
throw new UserFriendlyException("未找到符合条件的数据,请检查数据是否正确");
}
// 移除属性名前缀,简化后续处理
propList.ForEach(d =>
{
d.PropertyName = d.PropertyName.Replace("Structure.", "");
});
return _generalPropService.ConvertToSingleDto<StructureConfigDto>(propList);
}
/// <summary>
/// 删除轴配置
/// </summary>
public async Task DeleteAxis(int leafId)
{
await _generalPropService.DeleteArrayNodeByLeafId(leafId);
}
/// <summary>
/// 批量更新配置
/// </summary>
public async Task BatchUpdate(GeneralPropUpdateDto updateDto)
{
await _generalPropService.UpdateAsync(updateDto);
}
}
API 参考
GeneralPropService<TEntity, TPrimaryKey>
泛型服务类,提供动态属性的完整管理功能。
类型参数
TEntity: Entity, IDynamicPropEntity, IEntity<TPrimaryKey>- 动态属性实体类型,必须继承自 ABP 的 Entity 并实现 IDynamicPropEntity
TPrimaryKey: 主键类型(通常是 int 或 long)
构造函数
public GeneralPropService(IRepository<TEntity, TPrimaryKey> repository)
主要方法
| 方法 | 说明 | 返回类型 |
|---|---|---|
UpdateAsync |
批量更新属性值 | Task |
GetBuildPropList |
从 DTO 列表构建动态属性实体 | Task<List<TEntity>> |
DeleteArrayNodeByLeafId |
通过叶子节点 ID 删除整个数组节点 | Task |
ConvertToSingleDto |
将属性实体转换为单个 DTO | Task<T> |
ConvertToListDto |
将属性实体转换为 DTO 列表 | Task<List<T>> |
ListEntityToListOpenModel |
实体列表转 OpenModel 列表 | List<OpenModel> |
ListOpenModelToListEntity |
OpenModel 列表转实体列表 | List<TEntity> |
数据模型
⚠️ 1.1.0 变更:
GeneralPropUpdateDto和UpdatePropItemDto已迁移至OpenRobot.Framework.DynamicModel命名空间,请使用using OpenRobot.Framework.DynamicModel;导入。
GeneralPropUpdateDto
批量更新 DTO
// 命名空间:OpenRobot.Framework.DynamicModel
public class GeneralPropUpdateDto
{
public List<UpdatePropItemDto> Items { get; set; }
public int DynamicPropertyId { get; set; }
}
UpdatePropItemDto
单个更新项 DTO
// 命名空间:OpenRobot.Framework.DynamicModel
public class UpdatePropItemDto
{
public int Id { get; set; } // 属性记录 ID
public string PropName { get; set; } // 属性名称
public string PropValue { get; set; } // 新属性值
}
属性命名约定
- 点号分隔:嵌套属性使用点号分隔,如
Structure.Servos.Axis1.Name - 数组索引:数组属性通过
Index字段分组,相同 Index 的属性属于同一数组元素 - ParentID 格式:十六进制索引链,如
#00,#01,#02表示路径层级
验证元数据
通过 OpenModel 可以携带验证信息:
Title:属性显示名称(来自DescriptionAttribute)Regex:正则表达式(来自RegularExpressionAttribute)ErrorMessage:验证错误消息
依赖项
| 包名 | 版本 | 用途 |
|---|---|---|
| Abp | 9.4.2 | ASP.NET Boilerplate 框架 |
| Abp.EntityFrameworkCore | 9.4.2 | EF Core 集成 |
| OpenRobot.Framework.DynamicModel | 最新 | 动态模型核心库 |
系统要求
- .NET 8.0 或更高版本
扩展阅读
OpenRobot.Framework.DynamicModel- 动态模型核心库文档Test/StructureService.md- 完整的设备配置管理示例
许可证
本项目采用 MIT 许可证。
作者
OpenRobot
反馈与贡献
欢迎通过以下方式提供反馈:
- 提交 Issue
- 发起 Pull Request
- 联系维护者
版本历史
1.1.1 (2026-06-24)
- 数据构建ParentID 修复:修复数据对象构建 ParentID 少了一个层级导致的 读取失败
1.1.0 (2026-06-23)
- 数据模型迁移:
GeneralPropUpdateDto和UpdatePropItemDto迁移至OpenRobot.Framework.DynamicModel核心库,不再依赖本项目的Dto命名空间 - 更新
GeneralPropService引用,使用OpenRobot.Framework.DynamicModel下的数据类型 - 注意:如果之前从
OpenRobot.Framework.DynamicGeneralService.Dto引用这些类型,请改为引用OpenRobot.Framework.DynamicModel命名空间
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net8.0
- Abp (>= 9.4.2)
- Abp.EntityFrameworkCore (>= 9.4.2)
- OpenRobot.Framework.DynamicModel (>= 1.3.7)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.