diff --git a/aspnet-core/LINGYUN.MicroService.All.sln b/aspnet-core/LINGYUN.MicroService.All.sln index 4837ff981..453a3ab18 100644 --- a/aspnet-core/LINGYUN.MicroService.All.sln +++ b/aspnet-core/LINGYUN.MicroService.All.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30011.22 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{C5CAD011-DF84-4914-939C-0C029DCEF26F}" EndProject @@ -359,6 +359,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.UI.Navigation", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.UI.Navigation.VueVbenAdmin", "modules\platform\LINGYUN.Abp.UI.Navigation.VueVbenAdmin\LINGYUN.Abp.UI.Navigation.VueVbenAdmin.csproj", "{67A76560-D39F-4D49-B858-B476E1DFE37B}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dapr", "dapr", "{DC33925B-264D-421B-96CC-46F853CBCC70}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dapr", "modules\dapr\LINGYUN.Abp.Dapr\LINGYUN.Abp.Dapr.csproj", "{1B8FCBD9-8807-44E4-B91F-F4AB738CB26F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dapr.Client", "modules\dapr\LINGYUN.Abp.Dapr.Client\LINGYUN.Abp.Dapr.Client.csproj", "{93317D44-835C-4F5E-B85D-580D51D5FFF4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dapr.Actors", "modules\dapr\LINGYUN.Abp.Dapr.Actors\LINGYUN.Abp.Dapr.Actors.csproj", "{DAF80936-FBEC-45AB-92DF-34966B0148FD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Dapr.Actors.AspNetCore", "modules\dapr\LINGYUN.Abp.Dapr.Actors.AspNetCore\LINGYUN.Abp.Dapr.Actors.AspNetCore.csproj", "{995756A1-A379-4797-89F0-87D219B5AF00}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -937,6 +947,22 @@ Global {67A76560-D39F-4D49-B858-B476E1DFE37B}.Debug|Any CPU.Build.0 = Debug|Any CPU {67A76560-D39F-4D49-B858-B476E1DFE37B}.Release|Any CPU.ActiveCfg = Release|Any CPU {67A76560-D39F-4D49-B858-B476E1DFE37B}.Release|Any CPU.Build.0 = Release|Any CPU + {1B8FCBD9-8807-44E4-B91F-F4AB738CB26F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B8FCBD9-8807-44E4-B91F-F4AB738CB26F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B8FCBD9-8807-44E4-B91F-F4AB738CB26F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B8FCBD9-8807-44E4-B91F-F4AB738CB26F}.Release|Any CPU.Build.0 = Release|Any CPU + {93317D44-835C-4F5E-B85D-580D51D5FFF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93317D44-835C-4F5E-B85D-580D51D5FFF4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93317D44-835C-4F5E-B85D-580D51D5FFF4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93317D44-835C-4F5E-B85D-580D51D5FFF4}.Release|Any CPU.Build.0 = Release|Any CPU + {DAF80936-FBEC-45AB-92DF-34966B0148FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DAF80936-FBEC-45AB-92DF-34966B0148FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DAF80936-FBEC-45AB-92DF-34966B0148FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DAF80936-FBEC-45AB-92DF-34966B0148FD}.Release|Any CPU.Build.0 = Release|Any CPU + {995756A1-A379-4797-89F0-87D219B5AF00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {995756A1-A379-4797-89F0-87D219B5AF00}.Debug|Any CPU.Build.0 = Debug|Any CPU + {995756A1-A379-4797-89F0-87D219B5AF00}.Release|Any CPU.ActiveCfg = Release|Any CPU + {995756A1-A379-4797-89F0-87D219B5AF00}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1114,6 +1140,11 @@ Global {7D02D803-F9A9-492C-9B5E-454E4B258466} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} {FD04A084-BB8A-4733-B9C5-FACF40342A8A} = {7D02D803-F9A9-492C-9B5E-454E4B258466} {67A76560-D39F-4D49-B858-B476E1DFE37B} = {F4923692-D343-4318-AECA-96F580B1A563} + {DC33925B-264D-421B-96CC-46F853CBCC70} = {C5CAD011-DF84-4914-939C-0C029DCEF26F} + {1B8FCBD9-8807-44E4-B91F-F4AB738CB26F} = {DC33925B-264D-421B-96CC-46F853CBCC70} + {93317D44-835C-4F5E-B85D-580D51D5FFF4} = {DC33925B-264D-421B-96CC-46F853CBCC70} + {DAF80936-FBEC-45AB-92DF-34966B0148FD} = {DC33925B-264D-421B-96CC-46F853CBCC70} + {995756A1-A379-4797-89F0-87D219B5AF00} = {DC33925B-264D-421B-96CC-46F853CBCC70} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718} diff --git a/aspnet-core/LINGYUN.MicroService.Common.sln b/aspnet-core/LINGYUN.MicroService.Common.sln index 5e6c21124..ba6ffa7ca 100644 --- a/aspnet-core/LINGYUN.MicroService.Common.sln +++ b/aspnet-core/LINGYUN.MicroService.Common.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30011.22 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{02EA4E78-5891-43BC-944F-3E52FEE032E4}" EndProject @@ -188,10 +188,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtection" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtection.EntityFrameworkCore", "modules\data-protection\LINGYUN.Abp.DataProtection.EntityFrameworkCore\LINGYUN.Abp.DataProtection.EntityFrameworkCore.csproj", "{E16CCB14-E629-48E6-9603-53BBFF185318}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.DataProtection.Tests", "tests\LINGYUN.Abp.DataProtection.Tests\LINGYUN.Abp.DataProtection.Tests.csproj", "{FBE7D8CB-1D99-4342-A953-B9AB46E0B14D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtection.Tests", "tests\LINGYUN.Abp.DataProtection.Tests\LINGYUN.Abp.DataProtection.Tests.csproj", "{FBE7D8CB-1D99-4342-A953-B9AB46E0B14D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.EntityFrameworkCore.Tests\LINGYUN.Abp.EntityFrameworkCore.Tests.csproj", "{2F556889-006C-4A9C-8CA3-E31200C06FC9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Dapr", "modules\dapr\LINGYUN.Abp.Dapr\LINGYUN.Abp.Dapr.csproj", "{73C9A7E7-846D-49E2-B223-E705D6C48BE7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -498,6 +500,10 @@ Global {2F556889-006C-4A9C-8CA3-E31200C06FC9}.Debug|Any CPU.Build.0 = Debug|Any CPU {2F556889-006C-4A9C-8CA3-E31200C06FC9}.Release|Any CPU.ActiveCfg = Release|Any CPU {2F556889-006C-4A9C-8CA3-E31200C06FC9}.Release|Any CPU.Build.0 = Release|Any CPU + {73C9A7E7-846D-49E2-B223-E705D6C48BE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {73C9A7E7-846D-49E2-B223-E705D6C48BE7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {73C9A7E7-846D-49E2-B223-E705D6C48BE7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {73C9A7E7-846D-49E2-B223-E705D6C48BE7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -594,6 +600,7 @@ Global {E16CCB14-E629-48E6-9603-53BBFF185318} = {A0910407-CE69-4DC8-9721-F4324C22EEA8} {FBE7D8CB-1D99-4342-A953-B9AB46E0B14D} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} {2F556889-006C-4A9C-8CA3-E31200C06FC9} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} + {73C9A7E7-846D-49E2-B223-E705D6C48BE7} = {7FDFB22F-1BFF-4E05-9427-78B7A8461D50} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {06C707C6-02C0-411A-AD3B-2D0E13787CB8} diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors.AspNetCore/LINGYUN.Abp.Dapr.Actors.AspNetCore.csproj b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors.AspNetCore/LINGYUN.Abp.Dapr.Actors.AspNetCore.csproj index ff9bfd98e..1fee35da8 100644 --- a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors.AspNetCore/LINGYUN.Abp.Dapr.Actors.AspNetCore.csproj +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors.AspNetCore/LINGYUN.Abp.Dapr.Actors.AspNetCore.csproj @@ -8,7 +8,7 @@ - + diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors/LINGYUN.Abp.Dapr.Actors.csproj b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors/LINGYUN.Abp.Dapr.Actors.csproj index c05b49995..6ffd9e76a 100644 --- a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors/LINGYUN.Abp.Dapr.Actors.csproj +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Actors/LINGYUN.Abp.Dapr.Actors.csproj @@ -8,7 +8,7 @@ - + diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN.Abp.Dapr.Client.csproj b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN.Abp.Dapr.Client.csproj index 5a455a6e6..71c93a355 100644 --- a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN.Abp.Dapr.Client.csproj +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN.Abp.Dapr.Client.csproj @@ -1,13 +1,18 @@  + + net5.0 - + + + + diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN/Abp/Dapr/Client/AbpDaprClientModule.cs b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN/Abp/Dapr/Client/AbpDaprClientModule.cs index b792a1d10..34d9adb97 100644 --- a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN/Abp/Dapr/Client/AbpDaprClientModule.cs +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/LINGYUN/Abp/Dapr/Client/AbpDaprClientModule.cs @@ -1,24 +1,24 @@ -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Http.Client; -using Volo.Abp.Modularity; - -namespace LINGYUN.Abp.Dapr.Client -{ - [DependsOn( - typeof(AbpHttpClientModule) - )] - public class AbpDaprClientModule : AbpModule - { - /// - /// 与AbpHttpClient集成,创建一个命名HttpClient - /// - internal const string DaprHttpClient = "_AbpDaprProxyClient"; - - public override void ConfigureServices(ServiceConfigurationContext context) - { - var configuration = context.Services.GetConfiguration(); - Configure(configuration); - context.Services.AddHttpClient(DaprHttpClient); - } - } -} +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Http.Client; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Dapr.Client +{ + [DependsOn( + typeof(AbpHttpClientModule) + )] + public class AbpDaprClientModule : AbpModule + { + /// + /// 与AbpHttpClient集成,创建一个命名HttpClient + /// + internal const string DaprHttpClient = "_AbpDaprProxyClient"; + + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + Configure(configuration); + context.Services.AddHttpClient(DaprHttpClient); + } + } +} diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicDaprClientProxyExtensions.cs b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicDaprClientProxyExtensions.cs index bde7e72ff..a871e60ef 100644 --- a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicDaprClientProxyExtensions.cs +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Microsoft/Extensions/DependencyInjection/ServiceCollectionDynamicDaprClientProxyExtensions.cs @@ -1,257 +1,172 @@ -using Castle.DynamicProxy; -using Dapr.Client; -using JetBrains.Annotations; -using LINGYUN.Abp.Dapr.Client; -using LINGYUN.Abp.Dapr.Client.DynamicProxying; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; -using System; -using System.Linq; -using System.Reflection; -using Volo.Abp; -using Volo.Abp.Castle.DynamicProxy; -using Volo.Abp.Validation; - -namespace Microsoft.Extensions.DependencyInjection -{ - public static class ServiceCollectionDynamicDaprClientProxyExtensions - { - private static readonly ProxyGenerator ProxyGeneratorInstance = new ProxyGenerator(); - - #region Add DaprClient Builder - - public static IServiceCollection AddDaprClient( - [NotNull] this IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.AddLogging(); - services.AddOptions(); - - services.TryAddSingleton(); - services.TryAddSingleton(serviceProvider => serviceProvider.GetRequiredService()); - - return services; - } - - public static IDaprClientBuilder AddDaprClient( - [NotNull] this IServiceCollection services, - string name) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.AddDaprClient(); - - return new DefaultDaprClientBuilder(services, name); - } - - public static IDaprClientBuilder AddDaprClient( - [NotNull] this IServiceCollection services, - string name, - Action configureClient) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (configureClient == null) - { - throw new ArgumentNullException(nameof(configureClient)); - } - - services.AddDaprClient(); - - var builder = new DefaultDaprClientBuilder(services, name); - builder.ConfigureDaprClient(configureClient); - return builder; - } - - public static IDaprClientBuilder AddDaprClient( - [NotNull] this IServiceCollection services, - string name, - Action configureClient) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (configureClient == null) - { - throw new ArgumentNullException(nameof(configureClient)); - } - - services.AddDaprClient(); - var builder = new DefaultDaprClientBuilder(services, name); - builder.ConfigureDaprClient(configureClient); - return builder; - } - - - #endregion - - #region Add DaprClient Proxies - - public static IServiceCollection AddDaprClientProxies( - [NotNull] this IServiceCollection services, - [NotNull] Assembly assembly, - [NotNull] string remoteServiceConfigurationName = DaprRemoteServiceConfigurationDictionary.DefaultName, - bool asDefaultServices = true) - { - Check.NotNull(services, nameof(assembly)); - - var serviceTypes = assembly.GetTypes().Where(IsSuitableForDynamicActorProxying).ToArray(); - - foreach (var serviceType in serviceTypes) - { - services.AddDaprClientProxy( - serviceType, - remoteServiceConfigurationName, - asDefaultServices - ); - } - - return services; - } - - public static IServiceCollection AddDaprClientProxy( - [NotNull] this IServiceCollection services, - [NotNull] string remoteServiceConfigurationName = DaprRemoteServiceConfigurationDictionary.DefaultName, - bool asDefaultService = true) - { - return services.AddDaprClientProxy( - typeof(T), - remoteServiceConfigurationName, - asDefaultService - ); - } - - public static IServiceCollection AddDaprClientProxy( - [NotNull] this IServiceCollection services, - [NotNull] Type type, - [NotNull] string remoteServiceConfigurationName = DaprRemoteServiceConfigurationDictionary.DefaultName, - bool asDefaultService = true) - { - Check.NotNull(services, nameof(services)); - Check.NotNull(type, nameof(type)); - Check.NotNullOrWhiteSpace(remoteServiceConfigurationName, nameof(remoteServiceConfigurationName)); - - services.AddDaprClientFactory(remoteServiceConfigurationName); - - services.Configure(options => - { - options.DaprClientProxies[type] = new DynamicDaprClientProxyConfig(type, remoteServiceConfigurationName); - }); - - var interceptorType = typeof(DynamicDaprClientProxyInterceptor<>).MakeGenericType(type); - services.AddTransient(interceptorType); - - var interceptorAdapterType = typeof(AbpAsyncDeterminationInterceptor<>).MakeGenericType(interceptorType); - - var validationInterceptorAdapterType = - typeof(AbpAsyncDeterminationInterceptor<>).MakeGenericType(typeof(ValidationInterceptor)); - - if (asDefaultService) - { - services.AddTransient( - type, - serviceProvider => ProxyGeneratorInstance - .CreateInterfaceProxyWithoutTarget( - type, - (IInterceptor)serviceProvider.GetRequiredService(validationInterceptorAdapterType), - (IInterceptor)serviceProvider.GetRequiredService(interceptorAdapterType) - ) - ); - } - - services.AddTransient( - typeof(IDaprClientProxy<>).MakeGenericType(type), - serviceProvider => - { - var service = ProxyGeneratorInstance - .CreateInterfaceProxyWithoutTarget( - type, - (IInterceptor)serviceProvider.GetRequiredService(validationInterceptorAdapterType), - (IInterceptor)serviceProvider.GetRequiredService(interceptorAdapterType) - ); - - return Activator.CreateInstance( - typeof(DaprClientProxy<>).MakeGenericType(type), - service - ); - }); - - return services; - } - - private static IServiceCollection AddDaprClientFactory( - [NotNull] this IServiceCollection services, - [NotNull] string remoteServiceConfigurationName = DaprRemoteServiceConfigurationDictionary.DefaultName) - { - var preOptions = services.ExecutePreConfiguredActions(); - - if (preOptions.ConfiguredProxyClients.Contains(remoteServiceConfigurationName)) - { - return services; - } - - var clientBuilder = services.AddDaprClient(remoteServiceConfigurationName, (IServiceProvider provider, DaprClientBuilder builder) => - { - var options = provider.GetRequiredService>().Value; - builder.UseHttpEndpoint( - options.RemoteServices - .GetConfigurationOrDefault(remoteServiceConfigurationName).BaseUrl); - - foreach (var clientBuildAction in preOptions.ProxyClientBuildActions) - { - clientBuildAction(remoteServiceConfigurationName, provider, builder); - } - }); - - clientBuilder.ConfigureDaprClient((client) => - { - foreach (var clientBuildAction in preOptions.ProxyClientActions) - { - clientBuildAction(remoteServiceConfigurationName, client); - } - }); - - - services.PreConfigure(options => - { - options.ConfiguredProxyClients.Add(remoteServiceConfigurationName); - }); - - return services; - } - - private static bool IsSuitableForDynamicActorProxying(Type type) - { - //TODO: Add option to change type filter - - return type.IsInterface - && type.IsPublic - && !type.IsGenericType - && typeof(IRemoteService).IsAssignableFrom(type); - } - - #endregion - } -} +using Castle.DynamicProxy; +using Dapr.Client; +using JetBrains.Annotations; +using LINGYUN.Abp.Dapr.Client; +using LINGYUN.Abp.Dapr.Client.DynamicProxying; +using Microsoft.Extensions.Options; +using System; +using System.Linq; +using System.Reflection; +using Volo.Abp; +using Volo.Abp.Castle.DynamicProxy; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Validation; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class ServiceCollectionDynamicDaprClientProxyExtensions + { + private static readonly ProxyGenerator ProxyGeneratorInstance = new ProxyGenerator(); + + #region Add DaprClient Proxies + + public static IServiceCollection AddDaprClientProxies( + [NotNull] this IServiceCollection services, + [NotNull] Assembly assembly, + [NotNull] string remoteServiceConfigurationName = DaprRemoteServiceConfigurationDictionary.DefaultName, + bool asDefaultServices = true) + { + Check.NotNull(services, nameof(assembly)); + + var serviceTypes = assembly.GetTypes().Where(IsSuitableForDynamicActorProxying).ToArray(); + + foreach (var serviceType in serviceTypes) + { + services.AddDaprClientProxy( + serviceType, + remoteServiceConfigurationName, + asDefaultServices + ); + } + + return services; + } + + public static IServiceCollection AddDaprClientProxy( + [NotNull] this IServiceCollection services, + [NotNull] string remoteServiceConfigurationName = DaprRemoteServiceConfigurationDictionary.DefaultName, + bool asDefaultService = true) + { + return services.AddDaprClientProxy( + typeof(T), + remoteServiceConfigurationName, + asDefaultService + ); + } + + public static IServiceCollection AddDaprClientProxy( + [NotNull] this IServiceCollection services, + [NotNull] Type type, + [NotNull] string remoteServiceConfigurationName = DaprRemoteServiceConfigurationDictionary.DefaultName, + bool asDefaultService = true) + { + Check.NotNull(services, nameof(services)); + Check.NotNull(type, nameof(type)); + Check.NotNullOrWhiteSpace(remoteServiceConfigurationName, nameof(remoteServiceConfigurationName)); + + services.AddDaprClientFactory(remoteServiceConfigurationName); + + services.Configure(options => + { + options.DaprClientProxies[type] = new DynamicDaprClientProxyConfig(type, remoteServiceConfigurationName); + }); + + var interceptorType = typeof(DynamicDaprClientProxyInterceptor<>).MakeGenericType(type); + services.AddTransient(interceptorType); + + var interceptorAdapterType = typeof(AbpAsyncDeterminationInterceptor<>).MakeGenericType(interceptorType); + + var validationInterceptorAdapterType = + typeof(AbpAsyncDeterminationInterceptor<>).MakeGenericType(typeof(ValidationInterceptor)); + + if (asDefaultService) + { + services.AddTransient( + type, + serviceProvider => ProxyGeneratorInstance + .CreateInterfaceProxyWithoutTarget( + type, + (IInterceptor)serviceProvider.GetRequiredService(validationInterceptorAdapterType), + (IInterceptor)serviceProvider.GetRequiredService(interceptorAdapterType) + ) + ); + } + + services.AddTransient( + typeof(IDaprClientProxy<>).MakeGenericType(type), + serviceProvider => + { + var service = ProxyGeneratorInstance + .CreateInterfaceProxyWithoutTarget( + type, + (IInterceptor)serviceProvider.GetRequiredService(validationInterceptorAdapterType), + (IInterceptor)serviceProvider.GetRequiredService(interceptorAdapterType) + ); + + return Activator.CreateInstance( + typeof(DaprClientProxy<>).MakeGenericType(type), + service + ); + }); + + return services; + } + + private static IServiceCollection AddDaprClientFactory( + [NotNull] this IServiceCollection services, + [NotNull] string remoteServiceConfigurationName = DaprRemoteServiceConfigurationDictionary.DefaultName) + { + var preOptions = services.ExecutePreConfiguredActions(); + + if (preOptions.ConfiguredProxyClients.Contains(remoteServiceConfigurationName)) + { + return services; + } + + var clientBuilder = services.AddDaprClient(remoteServiceConfigurationName, (IServiceProvider provider, DaprClientBuilder builder) => + { + // TODO: 是否有必要? 使用框架的序列化配置 + var jsonOptions = provider.GetRequiredService>().Value; + builder.UseJsonSerializationOptions(jsonOptions.JsonSerializerOptions); + + var options = provider.GetRequiredService>().Value; + builder.UseHttpEndpoint( + options.RemoteServices + .GetConfigurationOrDefault(remoteServiceConfigurationName).BaseUrl); + + foreach (var clientBuildAction in preOptions.ProxyClientBuildActions) + { + clientBuildAction(remoteServiceConfigurationName, provider, builder); + } + }); + + clientBuilder.ConfigureDaprClient((client) => + { + foreach (var clientBuildAction in preOptions.ProxyClientActions) + { + clientBuildAction(remoteServiceConfigurationName, client); + } + }); + + + services.PreConfigure(options => + { + options.ConfiguredProxyClients.Add(remoteServiceConfigurationName); + }); + + return services; + } + + private static bool IsSuitableForDynamicActorProxying(Type type) + { + //TODO: Add option to change type filter + + return type.IsInterface + && type.IsPublic + && !type.IsGenericType + && typeof(IRemoteService).IsAssignableFrom(type); + } + + #endregion + } +} diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/DaprClientBuilderExtensions.cs b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/DaprClientBuilderExtensions.cs similarity index 97% rename from aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/DaprClientBuilderExtensions.cs rename to aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/DaprClientBuilderExtensions.cs index fef9d9732..11c7117eb 100644 --- a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/DaprClientBuilderExtensions.cs +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/DaprClientBuilderExtensions.cs @@ -1,72 +1,72 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using System; - -namespace Dapr.Client -{ - public static class DaprClientBuilderExtensions - { - public static IDaprClientBuilder ConfigureDaprClient(this IDaprClientBuilder builder, Action configureClient) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - if (configureClient == null) - { - throw new ArgumentNullException(nameof(configureClient)); - } - - builder.Services.Configure(builder.Name, options => - { - options.DaprClientActions.Add(configureClient); - }); - - return builder; - } - - public static IDaprClientBuilder ConfigureDaprClient(this IDaprClientBuilder builder, Action configureBuilder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - if (configureBuilder == null) - { - throw new ArgumentNullException(nameof(configureBuilder)); - } - - builder.Services.Configure(builder.Name, options => - { - options.DaprClientBuilderActions.Add(configureBuilder); - }); - - return builder; - } - - public static IDaprClientBuilder ConfigureDaprClient(this IDaprClientBuilder builder, Action configureClientBuilder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - if (configureClientBuilder == null) - { - throw new ArgumentNullException(nameof(configureClientBuilder)); - } - - builder.Services.AddTransient>(services => - { - return new ConfigureNamedOptions(builder.Name, (options) => - { - options.DaprClientBuilderActions.Add(client => configureClientBuilder(services, client)); - }); - }); - - return builder; - } - } -} +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using System; + +namespace Dapr.Client +{ + public static class DaprClientBuilderExtensions + { + public static IDaprClientBuilder ConfigureDaprClient(this IDaprClientBuilder builder, Action configureClient) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (configureClient == null) + { + throw new ArgumentNullException(nameof(configureClient)); + } + + builder.Services.Configure(builder.Name, options => + { + options.DaprClientActions.Add(configureClient); + }); + + return builder; + } + + public static IDaprClientBuilder ConfigureDaprClient(this IDaprClientBuilder builder, Action configureBuilder) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (configureBuilder == null) + { + throw new ArgumentNullException(nameof(configureBuilder)); + } + + builder.Services.Configure(builder.Name, options => + { + options.DaprClientBuilderActions.Add(configureBuilder); + }); + + return builder; + } + + public static IDaprClientBuilder ConfigureDaprClient(this IDaprClientBuilder builder, Action configureClientBuilder) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (configureClientBuilder == null) + { + throw new ArgumentNullException(nameof(configureClientBuilder)); + } + + builder.Services.AddTransient>(services => + { + return new ConfigureNamedOptions(builder.Name, (options) => + { + options.DaprClientBuilderActions.Add(client => configureClientBuilder(services, client)); + }); + }); + + return builder; + } + } +} diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/DaprClientFactoryOptions.cs b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/DaprClientFactoryOptions.cs similarity index 97% rename from aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/DaprClientFactoryOptions.cs rename to aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/DaprClientFactoryOptions.cs index 6a379ab74..6c4d156af 100644 --- a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/DaprClientFactoryOptions.cs +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/DaprClientFactoryOptions.cs @@ -1,21 +1,21 @@ -using Grpc.Net.Client; -using System; -using System.Collections.Generic; -using System.Text.Json; - -namespace Dapr.Client -{ - public class DaprClientFactoryOptions - { - public string DaprApiToken{ get; set; } - public string HttpEndpoint { get; set; } - public string GrpcEndpoint { get; set; } - public GrpcChannelOptions GrpcChannelOptions { get; set; } - public JsonSerializerOptions JsonSerializerOptions { get; set; } - public IList> DaprClientActions { get; } = new List>(); - public IList> DaprClientBuilderActions { get; } = new List>(); - public DaprClientFactoryOptions() - { - } - } -} +using Grpc.Net.Client; +using System; +using System.Collections.Generic; +using System.Text.Json; + +namespace Dapr.Client +{ + public class DaprClientFactoryOptions + { + public string DaprApiToken{ get; set; } + public string HttpEndpoint { get; set; } + public string GrpcEndpoint { get; set; } + public GrpcChannelOptions GrpcChannelOptions { get; set; } + public JsonSerializerOptions JsonSerializerOptions { get; set; } + public IList> DaprClientActions { get; } = new List>(); + public IList> DaprClientBuilderActions { get; } = new List>(); + public DaprClientFactoryOptions() + { + } + } +} diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/DefaultDaprClientBuilder.cs b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/DefaultDaprClientBuilder.cs similarity index 95% rename from aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/DefaultDaprClientBuilder.cs rename to aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/DefaultDaprClientBuilder.cs index 6a8a5da8d..8905a0d81 100644 --- a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/DefaultDaprClientBuilder.cs +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/DefaultDaprClientBuilder.cs @@ -1,17 +1,17 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace Dapr.Client -{ - internal class DefaultDaprClientBuilder : IDaprClientBuilder - { - public DefaultDaprClientBuilder(IServiceCollection services, string name) - { - Services = services; - Name = name; - } - - public string Name { get; } - - public IServiceCollection Services { get; } - } -} +using Microsoft.Extensions.DependencyInjection; + +namespace Dapr.Client +{ + internal class DefaultDaprClientBuilder : IDaprClientBuilder + { + public DefaultDaprClientBuilder(IServiceCollection services, string name) + { + Services = services; + Name = name; + } + + public string Name { get; } + + public IServiceCollection Services { get; } + } +} diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/DefaultDaprClientFactory.cs b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/DefaultDaprClientFactory.cs similarity index 97% rename from aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/DefaultDaprClientFactory.cs rename to aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/DefaultDaprClientFactory.cs index 909008e70..ba6efeb69 100644 --- a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/DefaultDaprClientFactory.cs +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/DefaultDaprClientFactory.cs @@ -1,82 +1,82 @@ -using Microsoft.Extensions.Options; -using System; -using System.Collections.Concurrent; -using System.Threading; - -namespace Dapr.Client -{ - public class DefaultDaprClientFactory : IDaprClientFactory - { - private readonly IOptionsMonitor _optionsMonitor; - - private readonly Func> _daprClientFactory; - internal readonly ConcurrentDictionary> _daprClients; - - public DefaultDaprClientFactory( - IOptionsMonitor optionsMonitor) - { - _optionsMonitor = optionsMonitor ?? throw new ArgumentNullException(nameof(optionsMonitor)); - - _daprClients = new ConcurrentDictionary>(); - - _daprClientFactory = (name) => - { - return new Lazy(() => - { - return InternalCreateDaprClient(name); - }, LazyThreadSafetyMode.ExecutionAndPublication); - }; - } - - public DaprClient CreateClient(string name) - { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - var client = _daprClients.GetOrAdd(name, _daprClientFactory).Value; - - var options = _optionsMonitor.Get(name); - for (int i = 0; i < options.DaprClientActions.Count; i++) - { - options.DaprClientActions[i](client); - } - - return client; - } - - internal DaprClient InternalCreateDaprClient(string name) - { - var builder = new DaprClientBuilder(); - - var options = _optionsMonitor.Get(name); - - if (!string.IsNullOrWhiteSpace(options.HttpEndpoint)) - { - builder.UseHttpEndpoint(options.HttpEndpoint); - } - if (!string.IsNullOrWhiteSpace(options.GrpcEndpoint)) - { - builder.UseGrpcEndpoint(options.GrpcEndpoint); - } - if (options.GrpcChannelOptions != null) - { - builder.UseGrpcChannelOptions(options.GrpcChannelOptions); - } - if (options.JsonSerializerOptions != null) - { - builder.UseJsonSerializationOptions(options.JsonSerializerOptions); - } - - builder.UseDaprApiToken(options.DaprApiToken); - - for (int i = 0; i < options.DaprClientBuilderActions.Count; i++) - { - options.DaprClientBuilderActions[i](builder); - } - - return builder.Build(); - } - } -} +using Microsoft.Extensions.Options; +using System; +using System.Collections.Concurrent; +using System.Threading; + +namespace Dapr.Client +{ + public class DefaultDaprClientFactory : IDaprClientFactory + { + private readonly IOptionsMonitor _optionsMonitor; + + private readonly Func> _daprClientFactory; + internal readonly ConcurrentDictionary> _daprClients; + + public DefaultDaprClientFactory( + IOptionsMonitor optionsMonitor) + { + _optionsMonitor = optionsMonitor ?? throw new ArgumentNullException(nameof(optionsMonitor)); + + _daprClients = new ConcurrentDictionary>(); + + _daprClientFactory = (name) => + { + return new Lazy(() => + { + return InternalCreateDaprClient(name); + }, LazyThreadSafetyMode.ExecutionAndPublication); + }; + } + + public DaprClient CreateClient(string name) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + var client = _daprClients.GetOrAdd(name, _daprClientFactory).Value; + + var options = _optionsMonitor.Get(name); + for (int i = 0; i < options.DaprClientActions.Count; i++) + { + options.DaprClientActions[i](client); + } + + return client; + } + + internal DaprClient InternalCreateDaprClient(string name) + { + var builder = new DaprClientBuilder(); + + var options = _optionsMonitor.Get(name); + + if (!string.IsNullOrWhiteSpace(options.HttpEndpoint)) + { + builder.UseHttpEndpoint(options.HttpEndpoint); + } + if (!string.IsNullOrWhiteSpace(options.GrpcEndpoint)) + { + builder.UseGrpcEndpoint(options.GrpcEndpoint); + } + if (options.GrpcChannelOptions != null) + { + builder.UseGrpcChannelOptions(options.GrpcChannelOptions); + } + if (options.JsonSerializerOptions != null) + { + builder.UseJsonSerializationOptions(options.JsonSerializerOptions); + } + + builder.UseDaprApiToken(options.DaprApiToken); + + for (int i = 0; i < options.DaprClientBuilderActions.Count; i++) + { + options.DaprClientBuilderActions[i](builder); + } + + return builder.Build(); + } + } +} diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/IDaprClientBuilder.cs b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/IDaprClientBuilder.cs similarity index 95% rename from aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/IDaprClientBuilder.cs rename to aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/IDaprClientBuilder.cs index 1e4122f0c..969c705be 100644 --- a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/IDaprClientBuilder.cs +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/IDaprClientBuilder.cs @@ -1,10 +1,10 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace Dapr.Client -{ - public interface IDaprClientBuilder - { - string Name { get; } - IServiceCollection Services { get; } - } -} +using Microsoft.Extensions.DependencyInjection; + +namespace Dapr.Client +{ + public interface IDaprClientBuilder + { + string Name { get; } + IServiceCollection Services { get; } + } +} diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/IDaprClientFactory.cs b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/IDaprClientFactory.cs similarity index 94% rename from aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/IDaprClientFactory.cs rename to aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/IDaprClientFactory.cs index 66bc3d13f..c6286f812 100644 --- a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr.Client/Dapr/Client/IDaprClientFactory.cs +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Dapr/Client/IDaprClientFactory.cs @@ -1,7 +1,7 @@ -namespace Dapr.Client -{ - public interface IDaprClientFactory - { - DaprClient CreateClient(string name); - } -} +namespace Dapr.Client +{ + public interface IDaprClientFactory + { + DaprClient CreateClient(string name); + } +} diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/LINGYUN.Abp.Dapr.csproj b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/LINGYUN.Abp.Dapr.csproj new file mode 100644 index 000000000..99847a048 --- /dev/null +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/LINGYUN.Abp.Dapr.csproj @@ -0,0 +1,15 @@ + + + + + + net5.0 + + + + + + + + + diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/LINGYUN/Abp/Dapr/AbpDaprModule.cs b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/LINGYUN/Abp/Dapr/AbpDaprModule.cs new file mode 100644 index 000000000..8928bbfd0 --- /dev/null +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/LINGYUN/Abp/Dapr/AbpDaprModule.cs @@ -0,0 +1,8 @@ +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Dapr +{ + public class AbpDaprModule : AbpModule + { + } +} diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Microsoft/Extensions/DependencyInjection/ServiceCollectionDaprClientExtensions.cs b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Microsoft/Extensions/DependencyInjection/ServiceCollectionDaprClientExtensions.cs new file mode 100644 index 000000000..e81508db2 --- /dev/null +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/Microsoft/Extensions/DependencyInjection/ServiceCollectionDaprClientExtensions.cs @@ -0,0 +1,99 @@ +using Dapr.Client; +using JetBrains.Annotations; +using Microsoft.Extensions.DependencyInjection.Extensions; +using System; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class ServiceCollectionDaprClientExtensions + { + #region Add DaprClient Builder + + public static IServiceCollection AddDaprClient( + [NotNull] this IServiceCollection services) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + services.AddLogging(); + services.AddOptions(); + + services.TryAddSingleton(); + services.TryAddSingleton(serviceProvider => serviceProvider.GetRequiredService()); + + return services; + } + + public static IDaprClientBuilder AddDaprClient( + [NotNull] this IServiceCollection services, + string name) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + services.AddDaprClient(); + + return new DefaultDaprClientBuilder(services, name); + } + + public static IDaprClientBuilder AddDaprClient( + [NotNull] this IServiceCollection services, + string name, + Action configureClient) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + if (configureClient == null) + { + throw new ArgumentNullException(nameof(configureClient)); + } + + services.AddDaprClient(); + + var builder = new DefaultDaprClientBuilder(services, name); + builder.ConfigureDaprClient(configureClient); + return builder; + } + + public static IDaprClientBuilder AddDaprClient( + [NotNull] this IServiceCollection services, + string name, + Action configureClient) + { + if (services == null) + { + throw new ArgumentNullException(nameof(services)); + } + + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + if (configureClient == null) + { + throw new ArgumentNullException(nameof(configureClient)); + } + + services.AddDaprClient(); + var builder = new DefaultDaprClientBuilder(services, name); + builder.ConfigureDaprClient(configureClient); + return builder; + } + + + #endregion + } +} diff --git a/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/README.md b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/README.md new file mode 100644 index 000000000..c1dec3987 --- /dev/null +++ b/aspnet-core/modules/dapr/LINGYUN.Abp.Dapr/README.md @@ -0,0 +1,26 @@ +# LINGYUN.Abp.Dapr + +Dapr 集成基础模块, 实现dapr文档中的命名单例DaprClient + +See: https://docs.dapr.io/developing-applications/sdks/dotnet/dotnet-client/dotnet-daprclient-usage + +## 配置使用 + +模块按需引用 + +```csharp +[DependsOn(typeof(AbpDaprModule))] +public class YouProjectModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + // 创建一个DaprClient + context.Services.AddDaprClient(); + + // 创建一个具名DaprClient + context.Services.AddDaprClient("__DaprClient"); + } +} +``` + +## 其他