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