From f3113a8a479b4402dd299df79bc451478b37edad Mon Sep 17 00:00:00 2001 From: colin Date: Wed, 26 Aug 2026 09:11:52 +0800 Subject: [PATCH] feat: Rewrite the default xxxDefinitionManager of abp --- .../FodyWeavers.xml | 3 + .../FodyWeavers.xsd | 30 +++ .../LINGYUN.Abp.Dynamic.Definitions.csproj | 27 ++ .../AbpDynamicDefinitionsModule.cs | 32 +++ .../FeatureDynamicDefinitionManager.cs | 253 ++++++++++++++++++ .../PermissionDynamicDefinitionManager.cs | 249 +++++++++++++++++ .../SettingDynamicDefinitionManager.cs | 82 ++++++ .../TemplateDynamicDefinitionManager.cs | 99 +++++++ 8 files changed, 775 insertions(+) create mode 100644 aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/FodyWeavers.xml create mode 100644 aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/FodyWeavers.xsd create mode 100644 aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN.Abp.Dynamic.Definitions.csproj create mode 100644 aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/AbpDynamicDefinitionsModule.cs create mode 100644 aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/FeatureDynamicDefinitionManager.cs create mode 100644 aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/PermissionDynamicDefinitionManager.cs create mode 100644 aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/SettingDynamicDefinitionManager.cs create mode 100644 aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/TemplateDynamicDefinitionManager.cs diff --git a/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/FodyWeavers.xml b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/FodyWeavers.xsd b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN.Abp.Dynamic.Definitions.csproj b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN.Abp.Dynamic.Definitions.csproj new file mode 100644 index 000000000..1e16ed5b0 --- /dev/null +++ b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN.Abp.Dynamic.Definitions.csproj @@ -0,0 +1,27 @@ + + + + + + + netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0 + LINGYUN.Abp.Dynamic.Definitions + LINGYUN.Abp.Dynamic.Definitions + false + false + false + + + + + + + + + + + + + + + diff --git a/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/AbpDynamicDefinitionsModule.cs b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/AbpDynamicDefinitionsModule.cs new file mode 100644 index 000000000..47fd99517 --- /dev/null +++ b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/AbpDynamicDefinitionsModule.cs @@ -0,0 +1,32 @@ +using Volo.Abp.Authorization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Features; +using Volo.Abp.Modularity; +using Volo.Abp.Settings; +using Volo.Abp.TextTemplating; + +namespace LINGYUN.Abp.Dynamic.Definitions; + +[DependsOn( + typeof(AbpFeaturesModule), + typeof(AbpAuthorizationModule), + typeof(AbpTextTemplatingCoreModule), + typeof(AbpDynamicDefinitionsCoreModule))] +public class AbpDynamicDefinitionsModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.MapStrategy(DynamicDefinitionStrategy.Merge); + options.MapStrategy(DynamicDefinitionStrategy.Merge); + + options.MapStrategy(DynamicDefinitionStrategy.Merge); + options.MapStrategy(DynamicDefinitionStrategy.Merge); + + options.MapStrategy(DynamicDefinitionStrategy.Merge); + + options.MapStrategy(DynamicDefinitionStrategy.Merge); + }); + } +} diff --git a/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/FeatureDynamicDefinitionManager.cs b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/FeatureDynamicDefinitionManager.cs new file mode 100644 index 000000000..8075a3665 --- /dev/null +++ b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/FeatureDynamicDefinitionManager.cs @@ -0,0 +1,253 @@ +using JetBrains.Annotations; +using Microsoft.Extensions.Options; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; + +namespace LINGYUN.Abp.Dynamic.Definitions; + +[Dependency(ReplaceServices = true)] +[ExposeServices( + typeof(IFeatureDefinitionManager), + typeof(FeatureDynamicDefinitionManager))] +public class FeatureDynamicDefinitionManager : + DynamicDefinitionManager, + IFeatureDefinitionManager, + ISingletonDependency +{ + protected IStaticFeatureDefinitionStore StaticStore { get; } + protected IDynamicFeatureDefinitionStore DynamicStore { get; } + public FeatureDynamicDefinitionManager( + IStaticFeatureDefinitionStore staticStore, + IDynamicFeatureDefinitionStore dynamicStore, + IOptions options) + : base(options) + { + StaticStore = staticStore; + DynamicStore = dynamicStore; + } + + public async virtual Task> GetAllAsync() + { + var staticDefinitions = await StaticStore.GetFeaturesAsync(); + var dynamicDefinitions = await DynamicStore.GetFeaturesAsync(); + + return await GetDefinitionsAsync(staticDefinitions, dynamicDefinitions); + } + + public async virtual Task GetAsync(string name) + { + return await GetOrNullAsync(name) ?? throw new AbpException("Undefined feature: " + name); + } + + public async virtual Task> GetGroupsAsync() + { + var staticGroupDefinitions = await StaticStore.GetGroupsAsync(); + var dynamicGroupDefinitions = await DynamicStore.GetGroupsAsync(); + + return await GetGroupDefinitionsAsync(staticGroupDefinitions, dynamicGroupDefinitions); + } + + public async virtual Task GetOrNullAsync(string name) + { + Check.NotNull(name, nameof(name)); + + var staticDefinition = await StaticStore.GetOrNullAsync(name); + var dynamicDefinition = await DynamicStore.GetOrNullAsync(name); + + return await GetDefinitionAsync(staticDefinition, dynamicDefinition); + } + + protected override string GetDefinitionKey(FeatureDefinition definition) + { + return definition.Name; + } + + protected override string GetGroupDefinitionKey(FeatureGroupDefinition groupDefinition) + { + return groupDefinition.Name; + } + + protected override Task MergeDefinitionAsync(FeatureDefinition targetDefinition, FeatureDefinition sourceDefinition) + { + targetDefinition.DisplayName = sourceDefinition.DisplayName; + + if (sourceDefinition.Description != null) + { + targetDefinition.Description = sourceDefinition.Description; + } + + if (sourceDefinition.DefaultValue != null) + { + targetDefinition.DefaultValue = sourceDefinition.DefaultValue; + } + + if (sourceDefinition.ValueType != null) + { + targetDefinition.ValueType = sourceDefinition.ValueType; + } + + targetDefinition.IsVisibleToClients = targetDefinition.IsVisibleToClients || sourceDefinition.IsVisibleToClients; + targetDefinition.IsAvailableToHost = targetDefinition.IsAvailableToHost || sourceDefinition.IsAvailableToHost; + + CopyFeatureDetails(targetDefinition, sourceDefinition); + + return Task.FromResult(targetDefinition); + } + + protected async override Task AfterMergeDefinitionAsync(FeatureDefinition targetDefinition, FeatureDefinition sourceDefinition) + { + foreach (var child in sourceDefinition.Children) + { + await MergeChildFeature(targetDefinition, child); + } + } + + protected async override Task MergeGroupDefinitionAsync(FeatureGroupDefinition targetGroupDefinition, FeatureGroupDefinition sourceGroupDefinition) + { + if (sourceGroupDefinition.DisplayName != null) + { + targetGroupDefinition.DisplayName = sourceGroupDefinition.DisplayName; + } + foreach (var property in sourceGroupDefinition.Properties) + { + targetGroupDefinition.Properties[property.Key] = property.Value; + } + + foreach (var sourceFeature in sourceGroupDefinition.Features) + { + var existingFeature = GetFeatureOrNull(targetGroupDefinition, sourceFeature.Name); + + if (existingFeature == null) + { + var newFeature = targetGroupDefinition.AddFeature( + sourceFeature.Name, + sourceFeature.DefaultValue, + sourceFeature.DisplayName, + sourceFeature.Description, + sourceFeature.ValueType, + sourceFeature.IsVisibleToClients, + sourceFeature.IsAvailableToHost + ); + + CopyFeatureDetails(sourceFeature, newFeature); + + foreach (var child in sourceFeature.Children) + { + AddChildFeatureRecursively(newFeature, child); + } + } + else + { + await MergeDefinitionAsync(existingFeature, sourceFeature); + + foreach (var child in sourceFeature.Children) + { + await MergeChildFeature(existingFeature, child); + } + } + } + } + + private async Task MergeChildFeature(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + else + { + await MergeDefinitionAsync(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + await MergeChildFeature(existingChild, grandchild); + } + } + } + + private static void AddChildFeatureRecursively(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + + private static void CopyFeatureDetails(FeatureDefinition source, FeatureDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + } + + public static FeatureDefinition? GetFeatureOrNull( + FeatureGroupDefinition group, + [NotNull] string name) + { + Check.NotNull(name, nameof(name)); + + return GetFeatureOrNullRecursively(group.Features, name); + } + + private static FeatureDefinition? GetFeatureOrNullRecursively( + IReadOnlyList features, + string name) + { + foreach (var feature in features) + { + if (feature.Name == name) + { + return feature; + } + + var childFeature = GetFeatureOrNullRecursively(feature.Children, name); + if (childFeature != null) + { + return childFeature; + } + } + + return null; + } +} diff --git a/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/PermissionDynamicDefinitionManager.cs b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/PermissionDynamicDefinitionManager.cs new file mode 100644 index 000000000..36eaa06c1 --- /dev/null +++ b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/PermissionDynamicDefinitionManager.cs @@ -0,0 +1,249 @@ +using Microsoft.Extensions.Options; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.Dynamic.Definitions; + +[Dependency(ReplaceServices = true)] +[ExposeServices( + typeof(IPermissionDefinitionManager), + typeof(PermissionDynamicDefinitionManager))] +public class PermissionDynamicDefinitionManager : + DynamicDefinitionManager, + IPermissionDefinitionManager, + ITransientDependency +{ + protected IStaticPermissionDefinitionStore StaticStore { get; } + protected IDynamicPermissionDefinitionStore DynamicStore { get; } + public PermissionDynamicDefinitionManager( + IStaticPermissionDefinitionStore staticStore, + IDynamicPermissionDefinitionStore dynamicStore, + IOptions options) : base(options) + { + StaticStore = staticStore; + DynamicStore = dynamicStore; + } + + public async virtual Task GetAsync(string name) + { + return await GetOrNullAsync(name) ?? throw new AbpException("Undefined permission: " + name); + } + + public async virtual Task> GetGroupsAsync() + { + var staticGroupDefinitions = await StaticStore.GetGroupsAsync(); + var dynamicGroupDefinitions = await DynamicStore.GetGroupsAsync(); + + return await GetGroupDefinitionsAsync(staticGroupDefinitions, dynamicGroupDefinitions); + } + + public async virtual Task GetOrNullAsync(string name) + { + Check.NotNull(name, nameof(name)); + + var staticDefinition = await StaticStore.GetOrNullAsync(name); + var dynamicDefinition = await DynamicStore.GetOrNullAsync(name); + + return await GetDefinitionAsync(staticDefinition, dynamicDefinition); + } + + public async virtual Task> GetPermissionsAsync() + { + var staticDefinitions = await StaticStore.GetPermissionsAsync(); + var dynamicDefinitions = await DynamicStore.GetPermissionsAsync(); + + return await GetDefinitionsAsync(staticDefinitions, dynamicDefinitions); + } + + public async virtual Task GetResourcePermissionAsync(string resourceName, string name) + { + return await GetResourcePermissionOrNullAsync(resourceName, name) + ?? throw new AbpException($"Undefined resource permission: {name} for resource: {resourceName}"); + } + + public async virtual Task GetResourcePermissionOrNullAsync(string resourceName, string name) + { + Check.NotNull(name, nameof(name)); + + var staticDefinition = await StaticStore.GetResourcePermissionOrNullAsync(resourceName, name); + var dynamicDefinition = await DynamicStore.GetResourcePermissionOrNullAsync(resourceName, name); + + return await GetDefinitionAsync(staticDefinition, dynamicDefinition); + } + + public async virtual Task> GetResourcePermissionsAsync() + { + var staticDefinitions = await StaticStore.GetResourcePermissionsAsync(); + var dynamicDefinitions = await DynamicStore.GetResourcePermissionsAsync(); + + return await GetDefinitionsAsync(staticDefinitions, dynamicDefinitions); + } + + protected override string GetDefinitionKey(PermissionDefinition definition) + { + return definition.Name; + } + + protected override string GetGroupDefinitionKey(PermissionGroupDefinition groupDefinition) + { + return groupDefinition.Name; + } + + protected override Task MergeDefinitionAsync(PermissionDefinition targetDefinition, PermissionDefinition sourceDefinition) + { + targetDefinition.DisplayName = sourceDefinition.DisplayName; + if (sourceDefinition.ResourceName != null) + { + targetDefinition.ResourceName = sourceDefinition.ResourceName; + } + if (sourceDefinition.ManagementPermissionName != null) + { + targetDefinition.ManagementPermissionName = sourceDefinition.ManagementPermissionName; + } + + if (sourceDefinition.MultiTenancySide != MultiTenancySides.Both) + { + targetDefinition.MultiTenancySide |= sourceDefinition.MultiTenancySide; + } + + targetDefinition.IsEnabled = targetDefinition.IsEnabled || sourceDefinition.IsEnabled; + + CopyPermissionDetails(targetDefinition, sourceDefinition); + + return Task.FromResult(targetDefinition); + } + + protected async override Task MergeGroupDefinitionAsync(PermissionGroupDefinition targetGroupDefinition, PermissionGroupDefinition sourceGroupDefinition) + { + if (sourceGroupDefinition.DisplayName != null) + { + targetGroupDefinition.DisplayName = sourceGroupDefinition.DisplayName; + } + foreach (var property in sourceGroupDefinition.Properties) + { + targetGroupDefinition.Properties[property.Key] = property.Value; + } + + foreach (var sourcePermission in sourceGroupDefinition.Permissions) + { + var existingPermission = targetGroupDefinition.GetPermissionOrNull(sourcePermission.Name); + + if (existingPermission == null) + { + var newPermission = targetGroupDefinition.AddPermission( + sourcePermission.Name, + sourcePermission.DisplayName, + sourcePermission.MultiTenancySide, + sourcePermission.IsEnabled + ); + newPermission.ResourceName = sourcePermission.ResourceName; + newPermission.ManagementPermissionName = sourcePermission.ManagementPermissionName; + + CopyPermissionDetails(sourcePermission, newPermission); + + foreach (var child in sourcePermission.Children) + { + AddChildPermissionRecursively(newPermission, child); + } + } + else + { + await MergeDefinitionAsync(existingPermission, sourcePermission); + + foreach (var sourceChild in sourcePermission.Children) + { + await MergeChildPermissions(existingPermission, sourceChild); + } + } + } + } + + protected async override Task AfterMergeDefinitionAsync(PermissionDefinition targetDefinition, PermissionDefinition sourceDefinition) + { + foreach (var child in sourceDefinition.Children) + { + await MergeChildPermissions(targetDefinition, child); + } + } + + private async Task MergeChildPermissions(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + newChild.ResourceName = sourceChild.ResourceName; + newChild.ManagementPermissionName = sourceChild.ManagementPermissionName; + + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + else + { + await MergeDefinitionAsync(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + await MergeChildPermissions(existingChild, grandchild); + } + } + } + + private static void AddChildPermissionRecursively(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + newChild.ResourceName = sourceChild.ResourceName; + newChild.ManagementPermissionName = sourceChild.ManagementPermissionName; + + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + + private static void CopyPermissionDetails(PermissionDefinition source, PermissionDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + } +} diff --git a/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/SettingDynamicDefinitionManager.cs b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/SettingDynamicDefinitionManager.cs new file mode 100644 index 000000000..833f90f99 --- /dev/null +++ b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/SettingDynamicDefinitionManager.cs @@ -0,0 +1,82 @@ +using Microsoft.Extensions.Options; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Settings; + +namespace LINGYUN.Abp.Dynamic.Definitions; + +[Dependency(ReplaceServices = true)] +[ExposeServices( + typeof(ISettingDefinitionManager), + typeof(SettingDynamicDefinitionManager))] +public class SettingDynamicDefinitionManager : + DynamicDefinitionManager, + ISettingDefinitionManager, + ISingletonDependency +{ + protected IStaticSettingDefinitionStore StaticStore { get; } + protected IDynamicSettingDefinitionStore DynamicStore { get; } + public SettingDynamicDefinitionManager( + IStaticSettingDefinitionStore staticStore, + IDynamicSettingDefinitionStore dynamicStore, + IOptions options) : base(options) + { + StaticStore = staticStore; + DynamicStore = dynamicStore; + } + + public async virtual Task> GetAllAsync() + { + var staticDefinitions = await StaticStore.GetAllAsync(); + var dynamicDefinitions = await DynamicStore.GetAllAsync(); + + return await GetDefinitionsAsync(staticDefinitions, dynamicDefinitions); + } + + public async virtual Task GetAsync(string name) + { + return await GetOrNullAsync(name) ?? throw new AbpException("Undefined setting: " + name); + } + + public async virtual Task GetOrNullAsync(string name) + { + Check.NotNull(name, nameof(name)); + + var staticDefinition = await StaticStore.GetOrNullAsync(name); + var dynamicDefinition = await DynamicStore.GetOrNullAsync(name); + + return await GetDefinitionAsync(staticDefinition, dynamicDefinition); + } + + protected override string GetDefinitionKey(SettingDefinition definition) + { + return definition.Name; + } + + protected override Task MergeDefinitionAsync(SettingDefinition targetDefinition, SettingDefinition sourceDefinition) + { + targetDefinition.DisplayName = sourceDefinition.DisplayName; + targetDefinition.Description = sourceDefinition.Description ?? targetDefinition.Description; + targetDefinition.DefaultValue = sourceDefinition.DefaultValue ?? targetDefinition.DefaultValue; + targetDefinition.IsVisibleToClients = targetDefinition.IsVisibleToClients || sourceDefinition.IsVisibleToClients; + targetDefinition.IsInherited = targetDefinition.IsInherited || sourceDefinition.IsInherited; + targetDefinition.IsEncrypted = targetDefinition.IsEncrypted || sourceDefinition.IsEncrypted; + + foreach (var property in sourceDefinition.Properties) + { + targetDefinition.Properties[property.Key] = property.Value; + } + + foreach (var provider in sourceDefinition.Providers) + { + if (!targetDefinition.Providers.Contains(provider)) + { + targetDefinition.Providers.Add(provider); + } + } + + return Task.FromResult(targetDefinition); + } +} diff --git a/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/TemplateDynamicDefinitionManager.cs b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/TemplateDynamicDefinitionManager.cs new file mode 100644 index 000000000..e489cb542 --- /dev/null +++ b/aspnet-core/framework/dynamic-definition/LINGYUN.Abp.Dynamic.Definitions/LINGYUN/Abp/Dynamic/Definitions/TemplateDynamicDefinitionManager.cs @@ -0,0 +1,99 @@ +using Microsoft.Extensions.Options; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace LINGYUN.Abp.Dynamic.Definitions; + +[Dependency(ReplaceServices = true)] +[ExposeServices( + typeof(ITemplateDefinitionManager), + typeof(TemplateDynamicDefinitionManager))] +public class TemplateDynamicDefinitionManager : + DynamicDefinitionManager, + ITemplateDefinitionManager, + ISingletonDependency +{ + protected IStaticTemplateDefinitionStore StaticStore { get; } + protected IDynamicTemplateDefinitionStore DynamicStore { get; } + + public TemplateDynamicDefinitionManager( + IStaticTemplateDefinitionStore staticStore, + IDynamicTemplateDefinitionStore dynamicStore, + IOptions options) : base(options) + { + StaticStore = staticStore; + DynamicStore = dynamicStore; + } + + public async virtual Task> GetAllAsync() + { + var staticDefinitions = await StaticStore.GetAllAsync(); + var dynamicDefinitions = await DynamicStore.GetAllAsync(); + + return await GetDefinitionsAsync(staticDefinitions, dynamicDefinitions); + } + + public async virtual Task GetAsync(string name) + { + return await GetOrNullAsync(name) ?? throw new AbpException("Undefined Template: " + name); + } + + public async virtual Task GetOrNullAsync(string name) + { + Check.NotNull(name, nameof(name)); + + var staticDefinition = await StaticStore.GetOrNullAsync(name); + var dynamicDefinition = await DynamicStore.GetOrNullAsync(name); + + return await GetDefinitionAsync(staticDefinition, dynamicDefinition); + } + + protected override string GetDefinitionKey(TemplateDefinition definition) + { + return definition.Name; + } + + protected override Task MergeDefinitionAsync(TemplateDefinition targetDefinition, TemplateDefinition sourceDefinition) + { + var localizationResourceName = sourceDefinition.LocalizationResourceName ?? targetDefinition.LocalizationResourceName; + var defaultCultureName = sourceDefinition.DefaultCultureName ?? targetDefinition.DefaultCultureName; + var displayName = sourceDefinition.DisplayName ?? targetDefinition.DisplayName; + var isLayout = sourceDefinition.IsLayout || targetDefinition.IsLayout; + var layout = sourceDefinition.Layout ?? targetDefinition.Layout; + + var mergedTemplate = new TemplateDefinition( + targetDefinition.Name, + localizationResourceName, + displayName, + isLayout, + layout, + defaultCultureName + ); + + foreach (var property in targetDefinition.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + foreach (var property in sourceDefinition.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + if (!string.IsNullOrEmpty(sourceDefinition.RenderEngine)) + { + mergedTemplate.RenderEngine = sourceDefinition.RenderEngine; + } + else if (!string.IsNullOrEmpty(targetDefinition.RenderEngine)) + { + mergedTemplate.RenderEngine = targetDefinition.RenderEngine; + } + + mergedTemplate.IsInlineLocalized = sourceDefinition.IsInlineLocalized || targetDefinition.IsInlineLocalized; + + return Task.FromResult(mergedTemplate); + } +}