Browse Source

Merge pull request #23410 from abpframework/IAsyncEnumerable

Client Proxy `IAsyncEnumerable<T>` support.
pull/23537/head
Enis Necipoglu 6 months ago
committed by GitHub
parent
commit
6c2a902e13
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 18
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs
  2. 39
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxying/CSharp/CSharpServiceProxyGenerator.cs
  3. 18
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs

18
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpMvcOptionsExtensions.cs

@ -1,5 +1,9 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Microsoft.Extensions.DependencyInjection;
@ -14,6 +18,7 @@ using Volo.Abp.AspNetCore.Mvc.Response;
using Volo.Abp.AspNetCore.Mvc.Uow;
using Volo.Abp.AspNetCore.Mvc.Validation;
using Volo.Abp.Content;
using Volo.Abp.Json.SystemTextJson.JsonConverters;
namespace Volo.Abp.AspNetCore.Mvc;
@ -32,6 +37,17 @@ internal static class AbpMvcOptionsExtensions
private static void AddFormatters(MvcOptions options)
{
options.OutputFormatters.Insert(0, new RemoteStreamContentOutputFormatter());
var systemTextJsonOutputFormatter = options.OutputFormatters
.Where(f => f is SystemTextJsonOutputFormatter)
.Cast<SystemTextJsonOutputFormatter>().FirstOrDefault();
if (systemTextJsonOutputFormatter != null)
{
options.OutputFormatters.Remove(systemTextJsonOutputFormatter);
var jsonOptions = new JsonSerializerOptions(systemTextJsonOutputFormatter.SerializerOptions);
jsonOptions.Converters.RemoveAll(x => x is ObjectToInferredTypesConverter);
options.OutputFormatters.Add(new SystemTextJsonOutputFormatter(jsonOptions));
}
}
private static void AddConventions(MvcOptions options, IServiceCollection services)

39
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxying/CSharp/CSharpServiceProxyGenerator.cs

@ -19,7 +19,7 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
private const string ProxyDirectory = "ClientProxies";
private readonly static string[] ServicePostfixes = { "AppService", "ApplicationService", "IntService", "IntegrationService" , "Service"};
private static readonly string[] ServicePostfixes = { "AppService", "ApplicationService", "IntService", "IntegrationService" , "Service"};
private const string AppServicePrefix = "Volo.Abp.Application.Services";
private const string NamespacePlaceholder = "<namespace>";
@ -29,7 +29,7 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
private const string ClassNamePlaceholder = "<className>";
private const string ServiceInterfacePlaceholder = "<serviceInterface>";
private const string DtoClassNamePlaceholder = "<dtoName>";
private readonly static string ClassTemplate = "// This file is automatically generated by ABP framework to use MVC Controllers from CSharp" +
private static readonly string ClassTemplate = "// This file is automatically generated by ABP framework to use MVC Controllers from CSharp" +
$"{Environment.NewLine}<using>" +
$"{Environment.NewLine}" +
$"{Environment.NewLine}// ReSharper disable once CheckNamespace" +
@ -44,7 +44,7 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
$"{Environment.NewLine}}}" +
$"{Environment.NewLine}";
private readonly static string ClassTemplateEmptyPart = "// This file is part of <className>, you can customize it here" +
private static readonly string ClassTemplateEmptyPart = "// This file is part of <className>, you can customize it here" +
$"{Environment.NewLine}// ReSharper disable once CheckNamespace" +
$"{Environment.NewLine}namespace <namespace>;" +
$"{Environment.NewLine}" +
@ -53,7 +53,7 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
$"{Environment.NewLine}}}" +
$"{Environment.NewLine}";
private readonly static string InterfaceTemplate = "// This file is automatically generated by ABP framework to use MVC Controllers from CSharp" +
private static readonly string InterfaceTemplate = "// This file is automatically generated by ABP framework to use MVC Controllers from CSharp" +
$"{Environment.NewLine}<using>" +
$"{Environment.NewLine}" +
$"{Environment.NewLine}// ReSharper disable once CheckNamespace" +
@ -65,7 +65,7 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
$"{Environment.NewLine}}}" +
$"{Environment.NewLine}";
private readonly static string DtoTemplate = "// This file is automatically generated by ABP framework to use MVC Controllers from CSharp" +
private static readonly string DtoTemplate = "// This file is automatically generated by ABP framework to use MVC Controllers from CSharp" +
$"{Environment.NewLine}<using>" +
$"{Environment.NewLine}" +
$"{Environment.NewLine}// ReSharper disable once CheckNamespace" +
@ -77,7 +77,7 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
$"{Environment.NewLine}}}" +
$"{Environment.NewLine}";
private readonly static List<string> ClassUsingNamespaceList = new()
private static readonly List<string> ClassUsingNamespaceList = new()
{
"using System;",
"using System.Collections.Generic;",
@ -90,7 +90,7 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
"using Volo.Abp.Http.Client.ClientProxying;"
};
private readonly static List<string> InterfaceUsingNamespaceList = new()
private static readonly List<string> InterfaceUsingNamespaceList = new()
{
"using System;",
"using System.Collections.Generic;",
@ -100,7 +100,7 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
"using Volo.Abp.Application.Services;"
};
private readonly static List<string> DtoUsingNamespaceList = new()
private static readonly List<string> DtoUsingNamespaceList = new()
{
"using System;",
"using System.Collections.Generic;",
@ -116,7 +116,7 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
{
}
public async override Task GenerateProxyAsync(GenerateProxyArgs args)
public override async Task GenerateProxyAsync(GenerateProxyArgs args)
{
CheckWorkDirectory(args.WorkDirectory);
CheckFolder(args.Folder);
@ -305,9 +305,16 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
StringBuilder methodBuilder,
List<string> usingNamespaceList)
{
var returnSign = returnTypeName == "void" ? "Task" : $"Task<{returnTypeName}>";
var isAsyncEnumerable = returnTypeName.StartsWith("IAsyncEnumerable<");
var asyncEnumerableTypeName = isAsyncEnumerable
? returnTypeName.Substring("IAsyncEnumerable<".Length, returnTypeName.Length - "IAsyncEnumerable<".Length - 1)
: null;
var returnSign = isAsyncEnumerable ? returnTypeName : returnTypeName == "void" ? "Task" : $"Task<{returnTypeName}>";
methodBuilder.AppendLine($"public virtual async {returnSign} {action.Name}(<args>)");
methodBuilder.AppendLine(isAsyncEnumerable
? $"public virtual {returnSign} {action.Name}(<args>)"
: $"public virtual async {returnSign} {action.Name}(<args>)");
foreach (var parameter in action.ParametersOnMethod)
{
@ -325,9 +332,11 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
var args = action.ParametersOnMethod.Any() ? argsTemplate : string.Empty;
methodBuilder.AppendLine(returnTypeName == "void"
? $" await RequestAsync(nameof({action.Name}), {args});"
: $" return await RequestAsync<{returnTypeName}>(nameof({action.Name}), {args});");
methodBuilder.AppendLine(isAsyncEnumerable
? $" return RequestAsyncEnumerable<{asyncEnumerableTypeName}>(nameof({action.Name}), {args});"
: returnTypeName == "void"
? $" await RequestAsync(nameof({action.Name}), {args});"
: $" return await RequestAsync<{returnTypeName}>(nameof({action.Name}), {args});");
foreach (var parameter in action.ParametersOnMethod)
{
@ -543,7 +552,7 @@ public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServi
{
AddGenericTypeUsingNamespace(typeName, usingNamespaceList);
}
var type = new StringBuilder();
var s1 = typeName.Split("<");
for (var i = 0; i < s1.Length; i++)

18
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
@ -17,6 +18,7 @@ using Volo.Abp.Http.Client.Proxying;
using Volo.Abp.Http.Modeling;
using Volo.Abp.Http.ProxyScripting.Generators;
using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Reflection;
using Volo.Abp.Threading;
@ -44,6 +46,7 @@ public class ClientProxyBase<TService> : ITransientDependency
protected ClientProxyUrlBuilder ClientProxyUrlBuilder => LazyServiceProvider.LazyGetRequiredService<ClientProxyUrlBuilder>();
protected ICurrentApiVersionInfo CurrentApiVersionInfo => LazyServiceProvider.LazyGetRequiredService<ICurrentApiVersionInfo>();
protected ILocalEventBus LocalEventBus => LazyServiceProvider.LazyGetRequiredService<ILocalEventBus>();
protected IOptions<AbpSystemTextJsonSerializerOptions>? SystemTextJsonSerializerOptions => LazyServiceProvider.LazyGetService<IOptions<AbpSystemTextJsonSerializerOptions>>();
protected virtual async Task RequestAsync(string methodName, ClientProxyRequestTypeValue? arguments = null)
{
@ -55,6 +58,21 @@ public class ClientProxyBase<TService> : ITransientDependency
return await RequestAsync<T>(BuildHttpProxyClientProxyContext(methodName, arguments));
}
protected virtual async IAsyncEnumerable<T> RequestAsyncEnumerable<T>(string methodName, ClientProxyRequestTypeValue? arguments = null)
{
var requestContext = BuildHttpProxyClientProxyContext(methodName, arguments);
var responseContent = await RequestAsync(requestContext);
var options = SystemTextJsonSerializerOptions?.Value.JsonSerializerOptions;
var stream = await responseContent.ReadAsStreamAsync();
var items = options != null
? System.Text.Json.JsonSerializer.DeserializeAsyncEnumerable<T>(stream, options)
: System.Text.Json.JsonSerializer.DeserializeAsyncEnumerable<T>(stream);
await foreach (var item in items)
{
yield return item!;
}
}
protected virtual ClientProxyRequestContext BuildHttpProxyClientProxyContext(string methodName, ClientProxyRequestTypeValue? arguments = null)
{
if (arguments == null)

Loading…
Cancel
Save