From 581bd22c24a75e4f9614b7922244819aa8a96bf0 Mon Sep 17 00:00:00 2001 From: TekH Date: Mon, 4 Aug 2025 14:01:13 +0200 Subject: [PATCH] feat(MappingOptions): add to configure UriBuilderOptions factories. - add WorkFlowServiceOptions for flexible configuration --- src/WorkFlow.API/Program.cs | 6 ++- src/WorkFlow.API/appsettings.Mapping.json | 17 ++++++ .../DependencyInjection.cs | 36 ++++++++++--- .../Mapping/MappingOptions.cs | 52 +++++++++++++++++++ .../Mapping/TfFileIconUriBuilderResolver.cs | 11 ++-- .../Mapping/TfFileUriBuilderResolver.cs | 11 ++-- 6 files changed, 113 insertions(+), 20 deletions(-) create mode 100644 src/WorkFlow.API/appsettings.Mapping.json create mode 100644 src/WorkFlow.Application/Mapping/MappingOptions.cs diff --git a/src/WorkFlow.API/Program.cs b/src/WorkFlow.API/Program.cs index 8720fca..ae2a8bb 100644 --- a/src/WorkFlow.API/Program.cs +++ b/src/WorkFlow.API/Program.cs @@ -47,7 +47,11 @@ try ?? throw new InvalidOperationException( "The 'MediatRLicense' configuration value is missing or empty." + "Please ensure it is properly set in the configuration source."); - builder.Services.AddWorkFlowServices(mediatRLicense).AddWorkFlowRepositories(); + builder.Services.AddWorkFlowServices(opt => + { + opt.MediatRLicense = mediatRLicense; + opt.ConfigMapping(config); + }).AddWorkFlowRepositories(); builder.Services.AddUserManager(); diff --git a/src/WorkFlow.API/appsettings.Mapping.json b/src/WorkFlow.API/appsettings.Mapping.json new file mode 100644 index 0000000..0c0c4c2 --- /dev/null +++ b/src/WorkFlow.API/appsettings.Mapping.json @@ -0,0 +1,17 @@ +{ + "MappingOptions": { + "TfFileUri": { + "Scheme": "https", + "Host": " dd-gan.digitaldata.works", + "Port": 8443, + "Path": "api/file" + }, + "TfFileIconUri": { + "Scheme": "https", + "Host": " dd-gan.digitaldata.works", + "Port": 8443, + "Path": "api/file", + "Query": "icon=true" + } + } +} \ No newline at end of file diff --git a/src/WorkFlow.Application/DependencyInjection.cs b/src/WorkFlow.Application/DependencyInjection.cs index 05dac04..0450bbf 100644 --- a/src/WorkFlow.Application/DependencyInjection.cs +++ b/src/WorkFlow.Application/DependencyInjection.cs @@ -1,30 +1,52 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using WorkFlow.Application.Mapping; namespace WorkFlow.Application; public static class DependencyInjection { - public static IServiceCollection AddWorkFlowServices(this IServiceCollection services, string mediatRLicense, Action? options = null) + public static IServiceCollection AddWorkFlowServices(this IServiceCollection services, Action? options = null) { - WorkFlowServiceOptions diOptions = new(); - options?.Invoke(diOptions); + WorkFlowServiceOptions sOptions = new(services); + options?.Invoke(sOptions); services.AddAutoMapper(typeof(MappingProfile).Assembly); services.AddMediatR(cfg => { cfg.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly); - cfg.LicenseKey = mediatRLicense; + cfg.LicenseKey = sOptions.MediatRLicense; }); - services.AddSingleton(diOptions.UriBuilderFactory()); + if(!sOptions.IsMappingConfigured) + services.Configure(_ => { }); + services.AddTransient(); + services.AddTransient(); return services; } public class WorkFlowServiceOptions { - public Func UriBuilderFactory { get; set; } = () => new UriBuilder(); + private readonly IServiceCollection _services; + + internal bool IsMappingConfigured { get; private set; } = false; + + public WorkFlowServiceOptions(IServiceCollection services) => _services = services; + + private void EnsureSingleMappingConfiguration(Action action) + { + if (IsMappingConfigured) + throw new InvalidOperationException("Mapping configuration has already been set."); + action(); + IsMappingConfigured = true; + } + + public void ConfigMapping(IConfiguration config) => EnsureSingleMappingConfiguration(() => _services.Configure(config)); + + public void ConfigMapping(Action options) => EnsureSingleMappingConfiguration(() => _services.Configure(options)); + + public string? MediatRLicense { get; set; } } } \ No newline at end of file diff --git a/src/WorkFlow.Application/Mapping/MappingOptions.cs b/src/WorkFlow.Application/Mapping/MappingOptions.cs new file mode 100644 index 0000000..b7a0771 --- /dev/null +++ b/src/WorkFlow.Application/Mapping/MappingOptions.cs @@ -0,0 +1,52 @@ +namespace WorkFlow.Application.Mapping; + +public class MappingOptions +{ + public UriBuilderOptions TfFileUri { get; set; } = new(); + + public UriBuilderOptions TfFileIconUri { get; set; } = new(); + + public class UriBuilderOptions + { + public string? Scheme { get; set; } + + public string? Host { get; set; } + + public int? Port { get; set; } + + private string _path = "/"; + + public string Path + { + get => _path; + set => _path = value.Trim('/'); + } + + private string _query = string.Empty; + + public string Query + { + get => _query; + set => _query = value.TrimStart('?'); + } + + public UriBuilder ToBuilder + { + get + { + var uriBuilder = new UriBuilder() + { + Scheme = Scheme ?? "http", + Host = Host ?? "localhost", + Path = Path, + Query = Query, + }; + + if (Port is int port) + uriBuilder.Port = port; + + return uriBuilder; + } + } + } +} \ No newline at end of file diff --git a/src/WorkFlow.Application/Mapping/TfFileIconUriBuilderResolver.cs b/src/WorkFlow.Application/Mapping/TfFileIconUriBuilderResolver.cs index 924fed1..afb5f5b 100644 --- a/src/WorkFlow.Application/Mapping/TfFileIconUriBuilderResolver.cs +++ b/src/WorkFlow.Application/Mapping/TfFileIconUriBuilderResolver.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Microsoft.Extensions.Options; using System.Web; using WorkFlow.Application.Dto; using WorkFlow.Domain.Entities; @@ -7,16 +8,14 @@ namespace WorkFlow.Application.Mapping; public class TfFileIconUriBuilderResolver : IValueResolver { - private readonly UriBuilder _uriBuilder; + private readonly Func _uriBuilderFactory; - public TfFileIconUriBuilderResolver(UriBuilder uriBuilder) => _uriBuilder = uriBuilder; + public TfFileIconUriBuilderResolver(IOptions options) => _uriBuilderFactory = () => options.Value.TfFileIconUri.ToBuilder; public UriBuilder? Resolve(TfFile source, TfFileDto destination, UriBuilder? destMember, ResolutionContext context) { - var builder = new UriBuilder(_uriBuilder.Uri) - { - Path = HttpUtility.UrlEncode(source.Icon) - }; + var builder = _uriBuilderFactory(); + builder.Path = HttpUtility.UrlEncode(source.Icon); return builder; } } \ No newline at end of file diff --git a/src/WorkFlow.Application/Mapping/TfFileUriBuilderResolver.cs b/src/WorkFlow.Application/Mapping/TfFileUriBuilderResolver.cs index 0bad70b..c6440ad 100644 --- a/src/WorkFlow.Application/Mapping/TfFileUriBuilderResolver.cs +++ b/src/WorkFlow.Application/Mapping/TfFileUriBuilderResolver.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Microsoft.Extensions.Options; using System.Web; using WorkFlow.Application.Dto; using WorkFlow.Domain.Entities; @@ -7,16 +8,14 @@ namespace WorkFlow.Application.Mapping; public class TfFileUriBuilderResolver : IValueResolver { - private readonly UriBuilder _uriBuilder; + private readonly Func _uriBuilderFactory; - public TfFileUriBuilderResolver(UriBuilder uriBuilder) => _uriBuilder = uriBuilder; + public TfFileUriBuilderResolver(IOptions options) => _uriBuilderFactory = () => options.Value.TfFileUri.ToBuilder; public UriBuilder? Resolve(TfFile source, TfFileDto destination, UriBuilder? destMember, ResolutionContext context) { - var builder = new UriBuilder(_uriBuilder.Uri) - { - Path = HttpUtility.UrlEncode(source.Path) - }; + var builder = _uriBuilderFactory(); + builder.Path = HttpUtility.UrlEncode(source.Path); return builder; } } \ No newline at end of file