Browse Source
1:labp 增加命令行**generate-proxy**,仅限于CSharp客户端代理,增加对于dapr客户端代理的支持,详情见**labp help generate-proxy**pull/684/head
6 changed files with 605 additions and 2 deletions
@ -0,0 +1,146 @@ |
|||||
|
using LINGYUN.Abp.Cli.ServiceProxying; |
||||
|
using LINGYUN.Abp.Cli.ServiceProxying.CSharp; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using System.IO; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Cli.Args; |
||||
|
using Volo.Abp.Cli.Commands; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
using VoloGenerateProxyArgs = Volo.Abp.Cli.ServiceProxying.GenerateProxyArgs; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.Commands; |
||||
|
|
||||
|
public class GenerateProxyCommand : IConsoleCommand, ITransientDependency |
||||
|
{ |
||||
|
public const string Name = "generate-proxy"; |
||||
|
|
||||
|
protected string CommandName => Name; |
||||
|
|
||||
|
protected IServiceScopeFactory ServiceScopeFactory { get; } |
||||
|
|
||||
|
public GenerateProxyCommand( |
||||
|
IServiceScopeFactory serviceScopeFactory) |
||||
|
{ |
||||
|
ServiceScopeFactory = serviceScopeFactory; |
||||
|
} |
||||
|
|
||||
|
public async Task ExecuteAsync(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
using (var scope = ServiceScopeFactory.CreateScope()) |
||||
|
{ |
||||
|
var serviceProxyGenerator = scope.ServiceProvider.GetRequiredService<CSharpServiceProxyGenerator>(); |
||||
|
|
||||
|
await serviceProxyGenerator.GenerateProxyAsync(BuildArgs(commandLineArgs)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private VoloGenerateProxyArgs BuildArgs(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
var provider = commandLineArgs.Options.GetOrNull(Options.Provider.Short, Options.Provider.Long); |
||||
|
var url = commandLineArgs.Options.GetOrNull(Options.Url.Short, Options.Url.Long); |
||||
|
var target = commandLineArgs.Options.GetOrNull(Options.Target.Long); |
||||
|
var module = commandLineArgs.Options.GetOrNull(Options.Module.Short, Options.Module.Long) ?? "app"; |
||||
|
var output = commandLineArgs.Options.GetOrNull(Options.Output.Short, Options.Output.Long); |
||||
|
var apiName = commandLineArgs.Options.GetOrNull(Options.ApiName.Short, Options.ApiName.Long); |
||||
|
var source = commandLineArgs.Options.GetOrNull(Options.Source.Short, Options.Source.Long); |
||||
|
var workDirectory = commandLineArgs.Options.GetOrNull(Options.WorkDirectory.Short, Options.WorkDirectory.Long) ?? Directory.GetCurrentDirectory(); |
||||
|
var folder = commandLineArgs.Options.GetOrNull(Options.Folder.Long); |
||||
|
|
||||
|
return new GenerateProxyArgs(CommandName, workDirectory, module, url, output, target, apiName, source, folder, provider, commandLineArgs.Options); |
||||
|
} |
||||
|
|
||||
|
public string GetUsageInfo() |
||||
|
{ |
||||
|
var sb = new StringBuilder(); |
||||
|
|
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Usage:"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine($" labp {CommandName}"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Options:"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("-m|--module <module-name> (default: 'app') The name of the backend module you wish to generate proxies for."); |
||||
|
sb.AppendLine("-wd|--working-directory <directory-path> Execution directory."); |
||||
|
sb.AppendLine("-u|--url <url> API definition URL from."); |
||||
|
sb.AppendLine("-p|--provider <client-proxy-provider> The client proxy provider(http, dapr)."); |
||||
|
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); |
||||
|
|
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Examples:"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine(" labp generate-proxy"); |
||||
|
sb.AppendLine(" labp generate-proxy -p dapr"); |
||||
|
sb.AppendLine(" labp generate-proxy -m identity -o Pages/Identity/client-proxies.js -url https://localhost:44302/"); |
||||
|
sb.AppendLine(" labp generate-proxy --folder MyProxies/InnerFolder -url https://localhost:44302/"); |
||||
|
|
||||
|
return sb.ToString(); |
||||
|
} |
||||
|
|
||||
|
public string GetShortDescription() |
||||
|
{ |
||||
|
return "Generates client service proxies and DTOs to consume HTTP APIs."; |
||||
|
} |
||||
|
|
||||
|
public static class Options |
||||
|
{ |
||||
|
public static class Provider |
||||
|
{ |
||||
|
public const string Short = "p"; |
||||
|
public const string Long = "provider"; |
||||
|
} |
||||
|
|
||||
|
public static class Module |
||||
|
{ |
||||
|
public const string Short = "m"; |
||||
|
public const string Long = "module"; |
||||
|
} |
||||
|
|
||||
|
public static class ApiName |
||||
|
{ |
||||
|
public const string Short = "a"; |
||||
|
public const string Long = "api-name"; |
||||
|
} |
||||
|
|
||||
|
public static class Source |
||||
|
{ |
||||
|
public const string Short = "s"; |
||||
|
public const string Long = "source"; |
||||
|
} |
||||
|
public static class Output |
||||
|
{ |
||||
|
public const string Short = "o"; |
||||
|
public const string Long = "output"; |
||||
|
} |
||||
|
|
||||
|
public static class Target |
||||
|
{ |
||||
|
public const string Long = "target"; |
||||
|
} |
||||
|
|
||||
|
public static class Prompt |
||||
|
{ |
||||
|
public const string Short = "p"; |
||||
|
public const string Long = "prompt"; |
||||
|
} |
||||
|
|
||||
|
public static class Folder |
||||
|
{ |
||||
|
public const string Long = "folder"; |
||||
|
} |
||||
|
|
||||
|
public static class Url |
||||
|
{ |
||||
|
public const string Short = "u"; |
||||
|
public const string Long = "url"; |
||||
|
} |
||||
|
|
||||
|
public static class WorkDirectory |
||||
|
{ |
||||
|
public const string Short = "wd"; |
||||
|
public const string Long = "working-directory"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,422 @@ |
|||||
|
using Microsoft.Extensions.Logging; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Cli; |
||||
|
using Volo.Abp.Cli.Commands; |
||||
|
using Volo.Abp.Cli.Http; |
||||
|
using Volo.Abp.Cli.ServiceProxying; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Http.Modeling; |
||||
|
using Volo.Abp.Json; |
||||
|
|
||||
|
using VoloGenerateProxyArgs = Volo.Abp.Cli.ServiceProxying.GenerateProxyArgs; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.ServiceProxying.CSharp; |
||||
|
|
||||
|
[Dependency(ReplaceServices = true)] |
||||
|
[ExposeServices(typeof(IServiceProxyGenerator), typeof(CSharpServiceProxyGenerator))] |
||||
|
public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase<CSharpServiceProxyGenerator>, ITransientDependency |
||||
|
{ |
||||
|
public const string Name = "CSHARP"; |
||||
|
|
||||
|
private const string UsingPlaceholder = "<using placeholder>"; |
||||
|
private const string MethodPlaceholder = "<method placeholder>"; |
||||
|
private const string ClassName = "<className>"; |
||||
|
private const string ServiceInterface = "<serviceInterface>"; |
||||
|
private readonly static string[] ServicePostfixes = { "AppService", "ApplicationService" , "Service"}; |
||||
|
private const string DefaultNamespace = "ClientProxies"; |
||||
|
private const string Namespace = "<namespace>"; |
||||
|
private const string DefaultProvider = "ClientProxyBase"; |
||||
|
private const string Provider = "<provider>"; |
||||
|
private const string AppServicePrefix = "Volo.Abp.Application.Services"; |
||||
|
private readonly string _clientProxyGeneratedTemplate = "// This file is automatically generated by ABP framework to use MVC Controllers from CSharp" + |
||||
|
$"{Environment.NewLine}<using placeholder>" + |
||||
|
$"{Environment.NewLine}" + |
||||
|
$"{Environment.NewLine}// ReSharper disable once CheckNamespace" + |
||||
|
$"{Environment.NewLine}namespace <namespace>;" + |
||||
|
$"{Environment.NewLine}" + |
||||
|
$"{Environment.NewLine}[Dependency(ReplaceServices = true)]" + |
||||
|
$"{Environment.NewLine}[ExposeServices(typeof(<serviceInterface>), typeof(<className>))]" + |
||||
|
$"{Environment.NewLine}public partial class <className> : <provider><<serviceInterface>>, <serviceInterface>" + |
||||
|
$"{Environment.NewLine}{{" + |
||||
|
$"{Environment.NewLine} <method placeholder>" + |
||||
|
$"{Environment.NewLine}}}" + |
||||
|
$"{Environment.NewLine}"; |
||||
|
private readonly string _clientProxyTemplate = "// This file is part of <className>, you can customize it here" + |
||||
|
$"{Environment.NewLine}// ReSharper disable once CheckNamespace" + |
||||
|
$"{Environment.NewLine}namespace <namespace>;" + |
||||
|
$"{Environment.NewLine}" + |
||||
|
$"{Environment.NewLine}public partial class <className>" + |
||||
|
$"{Environment.NewLine}{{" + |
||||
|
$"{Environment.NewLine}}}" + |
||||
|
$"{Environment.NewLine}"; |
||||
|
private readonly List<string> _usingNamespaceList = new() |
||||
|
{ |
||||
|
"using System;", |
||||
|
"using System.Threading.Tasks;", |
||||
|
"using Volo.Abp.Application.Dtos;", |
||||
|
"using Volo.Abp.Http.Client;", |
||||
|
"using Volo.Abp.Http.Modeling;", |
||||
|
"using Volo.Abp.DependencyInjection;", |
||||
|
"using Volo.Abp.Http.Client.ClientProxying;", |
||||
|
"using LINGYUN.Abp.Dapr;", |
||||
|
"using LINGYUN.Abp.Dapr.Client;", |
||||
|
"using LINGYUN.Abp.Dapr.Client.ClientProxying;" |
||||
|
}; |
||||
|
|
||||
|
public CSharpServiceProxyGenerator( |
||||
|
CliHttpClientFactory cliHttpClientFactory, |
||||
|
IJsonSerializer jsonSerializer) : |
||||
|
base(cliHttpClientFactory, jsonSerializer) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public async override Task GenerateProxyAsync(VoloGenerateProxyArgs args) |
||||
|
{ |
||||
|
CheckWorkDirectory(args.WorkDirectory); |
||||
|
CheckFolder(args.Folder); |
||||
|
|
||||
|
if (args.CommandName == RemoveProxyCommand.Name) |
||||
|
{ |
||||
|
RemoveClientProxyFile(args); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var applicationApiDescriptionModel = await GetApplicationApiDescriptionModelAsync(args); |
||||
|
|
||||
|
foreach (var controller in applicationApiDescriptionModel.Modules.Values.SelectMany(x => x.Controllers)) |
||||
|
{ |
||||
|
if (ShouldGenerateProxy(controller.Value)) |
||||
|
{ |
||||
|
await GenerateClientProxyFileAsync(args, controller.Value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
await CreateGenerateProxyJsonFile(args, applicationApiDescriptionModel); |
||||
|
} |
||||
|
|
||||
|
private async Task CreateGenerateProxyJsonFile(VoloGenerateProxyArgs args, ApplicationApiDescriptionModel applicationApiDescriptionModel) |
||||
|
{ |
||||
|
var folder = args.Folder.IsNullOrWhiteSpace() ? DefaultNamespace : args.Folder; |
||||
|
var filePath = Path.Combine(args.WorkDirectory, folder, $"{args.Module}-generate-proxy.json"); |
||||
|
|
||||
|
using (var writer = new StreamWriter(filePath)) |
||||
|
{ |
||||
|
await writer.WriteAsync(JsonSerializer.Serialize(applicationApiDescriptionModel, indented: true)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void RemoveClientProxyFile(VoloGenerateProxyArgs args) |
||||
|
{ |
||||
|
var folder = args.Folder.IsNullOrWhiteSpace() ? DefaultNamespace : args.Folder; |
||||
|
var folderPath = Path.Combine(args.WorkDirectory, folder); |
||||
|
|
||||
|
if (Directory.Exists(folderPath)) |
||||
|
{ |
||||
|
Directory.Delete(folderPath, true); |
||||
|
} |
||||
|
|
||||
|
Logger.LogInformation($"Delete {GetLoggerOutputPath(folderPath, args.WorkDirectory)}"); |
||||
|
} |
||||
|
|
||||
|
private async Task GenerateClientProxyFileAsync( |
||||
|
VoloGenerateProxyArgs args, |
||||
|
ControllerApiDescriptionModel controllerApiDescription) |
||||
|
{ |
||||
|
var folder = args.Folder.IsNullOrWhiteSpace() ? DefaultNamespace : args.Folder; |
||||
|
|
||||
|
var appServiceTypeFullName = controllerApiDescription.Interfaces.Last().Type; |
||||
|
var appServiceTypeName = appServiceTypeFullName.Split('.').Last(); |
||||
|
var clientProxyName = $"{controllerApiDescription.ControllerName}ClientProxy"; |
||||
|
var clientProvider = args.As<GenerateProxyArgs>().Provider; |
||||
|
var rootNamespace = $"{GetTypeNamespace(controllerApiDescription.Type)}.{folder.Replace('/', '.')}"; |
||||
|
var clientProxyBuilder = new StringBuilder(_clientProxyTemplate); |
||||
|
clientProxyBuilder.Replace(ClassName, clientProxyName); |
||||
|
clientProxyBuilder.Replace(Namespace, rootNamespace); |
||||
|
clientProxyBuilder.Replace(Provider, clientProvider); |
||||
|
|
||||
|
var filePath = Path.Combine(args.WorkDirectory, folder, $"{clientProxyName}.cs"); |
||||
|
Directory.CreateDirectory(Path.GetDirectoryName(filePath)); |
||||
|
|
||||
|
if (!File.Exists(filePath)) |
||||
|
{ |
||||
|
using (var writer = new StreamWriter(filePath)) |
||||
|
{ |
||||
|
await writer.WriteAsync(clientProxyBuilder.ToString()); |
||||
|
} |
||||
|
|
||||
|
Logger.LogInformation($"Create {GetLoggerOutputPath(filePath, args.WorkDirectory)}"); |
||||
|
} |
||||
|
|
||||
|
await GenerateClientProxyGeneratedFileAsync( |
||||
|
args, |
||||
|
controllerApiDescription, |
||||
|
clientProxyName, |
||||
|
appServiceTypeName, |
||||
|
appServiceTypeFullName, |
||||
|
rootNamespace, |
||||
|
folder); |
||||
|
} |
||||
|
|
||||
|
private async Task GenerateClientProxyGeneratedFileAsync( |
||||
|
VoloGenerateProxyArgs args, |
||||
|
ControllerApiDescriptionModel controllerApiDescription, |
||||
|
string clientProxyName, |
||||
|
string appServiceTypeName, |
||||
|
string appServiceTypeFullName, |
||||
|
string rootNamespace, |
||||
|
string folder) |
||||
|
{ |
||||
|
var clientProxyBuilder = new StringBuilder(_clientProxyGeneratedTemplate); |
||||
|
|
||||
|
var usingNamespaceList = new List<string>(_usingNamespaceList) |
||||
|
{ |
||||
|
$"using {GetTypeNamespace(appServiceTypeFullName)};" |
||||
|
}; |
||||
|
|
||||
|
clientProxyBuilder.Replace(ClassName, clientProxyName); |
||||
|
clientProxyBuilder.Replace(Namespace, rootNamespace); |
||||
|
clientProxyBuilder.Replace(ServiceInterface, appServiceTypeName); |
||||
|
|
||||
|
foreach (var action in controllerApiDescription.Actions.Values) |
||||
|
{ |
||||
|
if (!ShouldGenerateMethod(appServiceTypeFullName, action)) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
GenerateMethod(action, clientProxyBuilder, usingNamespaceList); |
||||
|
} |
||||
|
|
||||
|
foreach (var usingNamespace in usingNamespaceList) |
||||
|
{ |
||||
|
clientProxyBuilder.Replace($"{UsingPlaceholder}", $"{usingNamespace}{Environment.NewLine}{UsingPlaceholder}"); |
||||
|
} |
||||
|
|
||||
|
clientProxyBuilder.Replace($"{Environment.NewLine}{UsingPlaceholder}", string.Empty); |
||||
|
clientProxyBuilder.Replace($"{Environment.NewLine}{Environment.NewLine} {MethodPlaceholder}", string.Empty); |
||||
|
|
||||
|
var filePath = Path.Combine(args.WorkDirectory, folder, $"{clientProxyName}.Generated.cs"); |
||||
|
|
||||
|
using (var writer = new StreamWriter(filePath)) |
||||
|
{ |
||||
|
await writer.WriteAsync(clientProxyBuilder.ToString()); |
||||
|
Logger.LogInformation($"Create {GetLoggerOutputPath(filePath, args.WorkDirectory)}"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void GenerateMethod( |
||||
|
ActionApiDescriptionModel action, |
||||
|
StringBuilder clientProxyBuilder, |
||||
|
List<string> usingNamespaceList) |
||||
|
{ |
||||
|
var methodBuilder = new StringBuilder(); |
||||
|
|
||||
|
var returnTypeName = GetRealTypeName(action.ReturnValue.Type, usingNamespaceList); |
||||
|
|
||||
|
if (!action.Name.EndsWith("Async")) |
||||
|
{ |
||||
|
GenerateSynchronizationMethod(action, returnTypeName, methodBuilder, usingNamespaceList); |
||||
|
clientProxyBuilder.Replace(MethodPlaceholder, $"{methodBuilder}{Environment.NewLine} {MethodPlaceholder}"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
GenerateAsynchronousMethod(action, returnTypeName, methodBuilder, usingNamespaceList); |
||||
|
clientProxyBuilder.Replace(MethodPlaceholder, $"{methodBuilder}{Environment.NewLine} {MethodPlaceholder}"); |
||||
|
} |
||||
|
|
||||
|
private void GenerateSynchronizationMethod(ActionApiDescriptionModel action, string returnTypeName, StringBuilder methodBuilder, List<string> usingNamespaceList) |
||||
|
{ |
||||
|
methodBuilder.AppendLine($"public virtual {returnTypeName} {action.Name}(<args>)"); |
||||
|
|
||||
|
foreach (var parameter in action.Parameters.GroupBy(x => x.Name).Select(x => x.First())) |
||||
|
{ |
||||
|
methodBuilder.Replace("<args>", $"{GetRealTypeName(parameter.Type, usingNamespaceList)} {parameter.Name}, <args>"); |
||||
|
} |
||||
|
|
||||
|
methodBuilder.Replace("<args>", string.Empty); |
||||
|
methodBuilder.Replace(", )", ")"); |
||||
|
|
||||
|
methodBuilder.AppendLine(" {"); |
||||
|
methodBuilder.AppendLine(" //Client Proxy does not support the synchronization method, you should always use asynchronous methods as a best practice"); |
||||
|
methodBuilder.AppendLine(" throw new System.NotImplementedException(); "); |
||||
|
methodBuilder.AppendLine(" }"); |
||||
|
} |
||||
|
|
||||
|
private void GenerateAsynchronousMethod( |
||||
|
ActionApiDescriptionModel action, |
||||
|
string returnTypeName, |
||||
|
StringBuilder methodBuilder, |
||||
|
List<string> usingNamespaceList) |
||||
|
{ |
||||
|
var returnSign = returnTypeName == "void" ? "Task" : $"Task<{returnTypeName}>"; |
||||
|
|
||||
|
methodBuilder.AppendLine($"public virtual async {returnSign} {action.Name}(<args>)"); |
||||
|
|
||||
|
foreach (var parameter in action.ParametersOnMethod) |
||||
|
{ |
||||
|
methodBuilder.Replace("<args>", $"{GetRealTypeName(parameter.Type, usingNamespaceList)} {parameter.Name}, <args>"); |
||||
|
} |
||||
|
|
||||
|
methodBuilder.Replace("<args>", string.Empty); |
||||
|
methodBuilder.Replace(", )", ")"); |
||||
|
|
||||
|
methodBuilder.AppendLine(" {"); |
||||
|
|
||||
|
var argsTemplate = "new ClientProxyRequestTypeValue" + |
||||
|
$"{Environment.NewLine} {{<args>" + |
||||
|
$"{Environment.NewLine} }}"; |
||||
|
|
||||
|
var args = action.ParametersOnMethod.Any() ? argsTemplate : string.Empty; |
||||
|
|
||||
|
if (returnTypeName == "void") |
||||
|
{ |
||||
|
methodBuilder.AppendLine($" await RequestAsync(nameof({action.Name}), {args});"); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
methodBuilder.AppendLine($" return await RequestAsync<{returnTypeName}>(nameof({action.Name}), {args});"); |
||||
|
} |
||||
|
|
||||
|
foreach (var parameter in action.ParametersOnMethod) |
||||
|
{ |
||||
|
methodBuilder.Replace("<args>", $"{Environment.NewLine} {{ typeof({GetRealTypeName(parameter.Type)}), {parameter.Name} }},<args>"); |
||||
|
} |
||||
|
|
||||
|
methodBuilder.Replace(",<args>", string.Empty); |
||||
|
methodBuilder.Replace(", )", ")"); |
||||
|
methodBuilder.AppendLine(" }"); |
||||
|
} |
||||
|
|
||||
|
private bool ShouldGenerateProxy(ControllerApiDescriptionModel controllerApiDescription) |
||||
|
{ |
||||
|
if (!controllerApiDescription.Interfaces.Any()) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
var serviceInterface = controllerApiDescription.Interfaces.Last(); |
||||
|
return ServicePostfixes.Any(x => serviceInterface.Type.EndsWith(x)); |
||||
|
} |
||||
|
|
||||
|
private bool ShouldGenerateMethod(string appServiceTypeName, ActionApiDescriptionModel action) |
||||
|
{ |
||||
|
return action.ImplementFrom.StartsWith(AppServicePrefix) || action.ImplementFrom.StartsWith(appServiceTypeName); |
||||
|
} |
||||
|
|
||||
|
private string GetTypeNamespace(string typeFullName) |
||||
|
{ |
||||
|
return typeFullName.Substring(0, typeFullName.LastIndexOf('.')); |
||||
|
} |
||||
|
|
||||
|
private string GetRealTypeName(string typeName, List<string> usingNamespaceList = null) |
||||
|
{ |
||||
|
var filter = new[] { "<", ",", ">" }; |
||||
|
var stringBuilder = new StringBuilder(); |
||||
|
var typeNames = typeName.Split('.'); |
||||
|
|
||||
|
if (typeNames.All(x => !filter.Any(x.Contains))) |
||||
|
{ |
||||
|
if (usingNamespaceList != null) |
||||
|
{ |
||||
|
AddUsingNamespace(usingNamespaceList, typeName); |
||||
|
} |
||||
|
|
||||
|
return NormalizeTypeName(typeNames.Last()); |
||||
|
} |
||||
|
|
||||
|
var fullName = string.Empty; |
||||
|
|
||||
|
foreach (var item in typeNames) |
||||
|
{ |
||||
|
if (filter.Any(x => item.Contains(x))) |
||||
|
{ |
||||
|
if (usingNamespaceList != null) |
||||
|
{ |
||||
|
AddUsingNamespace(usingNamespaceList, $"{fullName}.{item}".TrimStart('.')); |
||||
|
} |
||||
|
|
||||
|
fullName = string.Empty; |
||||
|
|
||||
|
if (item.Contains('<') || item.Contains(',')) |
||||
|
{ |
||||
|
stringBuilder.Append(item.Substring(0, item.IndexOf(item.Contains('<') ? '<' : ',') + 1)); |
||||
|
fullName = item.Substring(item.IndexOf(item.Contains('<') ? '<' : ',') + 1); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
stringBuilder.Append(item); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
fullName = $"{fullName}.{item}"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return stringBuilder.ToString(); |
||||
|
} |
||||
|
|
||||
|
private void AddUsingNamespace(List<string> usingNamespaceList, string typeName) |
||||
|
{ |
||||
|
var rootNamespace = $"using {GetTypeNamespace(typeName)};"; |
||||
|
if (usingNamespaceList.Contains(rootNamespace)) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
usingNamespaceList.Add(rootNamespace); |
||||
|
} |
||||
|
|
||||
|
private string NormalizeTypeName(string typeName) |
||||
|
{ |
||||
|
var nullable = string.Empty; |
||||
|
if (typeName.EndsWith("?")) |
||||
|
{ |
||||
|
typeName = typeName.TrimEnd('?'); |
||||
|
nullable = "?"; |
||||
|
} |
||||
|
|
||||
|
typeName = typeName switch |
||||
|
{ |
||||
|
"Void" => "void", |
||||
|
"Boolean" => "bool", |
||||
|
"String" => "string", |
||||
|
"Int32" => "int", |
||||
|
"Int64" => "long", |
||||
|
"Double" => "double", |
||||
|
"Object" => "object", |
||||
|
"Byte" => "byte", |
||||
|
"Char" => "char", |
||||
|
_ => typeName |
||||
|
}; |
||||
|
|
||||
|
return $"{typeName}{nullable}"; |
||||
|
} |
||||
|
|
||||
|
private void CheckWorkDirectory(string directory) |
||||
|
{ |
||||
|
if (!Directory.Exists(directory)) |
||||
|
{ |
||||
|
throw new CliUsageException("Specified directory does not exist."); |
||||
|
} |
||||
|
|
||||
|
var projectFiles = Directory.GetFiles(directory, "*.csproj"); |
||||
|
if (!projectFiles.Any()) |
||||
|
{ |
||||
|
throw new CliUsageException("No project file(csproj) found in the directory."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void CheckFolder(string folder) |
||||
|
{ |
||||
|
if (!folder.IsNullOrWhiteSpace() && Path.HasExtension(folder)) |
||||
|
{ |
||||
|
throw new CliUsageException("Option folder should be a directory."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Diagnostics.CodeAnalysis; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.ServiceProxying; |
||||
|
|
||||
|
public class GenerateProxyArgs : Volo.Abp.Cli.ServiceProxying.GenerateProxyArgs |
||||
|
{ |
||||
|
public string Provider { get; } |
||||
|
|
||||
|
public GenerateProxyArgs( |
||||
|
[NotNull] string commandName, |
||||
|
[NotNull] string workDirectory, |
||||
|
string module, |
||||
|
string url, |
||||
|
string output, |
||||
|
string target, |
||||
|
string apiName, |
||||
|
string source, |
||||
|
string folder, |
||||
|
string provider, |
||||
|
Dictionary<string, string> extraProperties = null) |
||||
|
: base(commandName, workDirectory, module, url, output, target, apiName, source, folder, extraProperties) |
||||
|
{ |
||||
|
Provider = provider; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue