Browse Source

Generate part class

pull/9905/head
liangshiwei 5 years ago
parent
commit
caad12a815
  1. 17
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GenerateProxyCommand.cs
  2. 37
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProxyCommandBase.cs
  3. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/RemoveProxyCommand.cs
  4. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxy/Angular/AngularServiceProxyGenerator.cs
  5. 113
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxy/CSharp/CSharpServiceProxyGenerator.cs
  6. 4
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxy/GenerateProxyArgs.cs
  7. 29
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxy/JavaScript/JavaScriptServiceProxyGenerator.cs
  8. 16
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxyBase.cs
  9. 2
      framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs

17
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/GenerateProxyCommand.cs

@ -1,3 +1,4 @@
using System.Text;
using Microsoft.Extensions.Options;
using Volo.Abp.Cli.ServiceProxy;
using Volo.Abp.DependencyInjection;
@ -17,9 +18,23 @@ namespace Volo.Abp.Cli.Commands
{
}
public override string GetUsageInfo()
{
var sb = new StringBuilder(base.GetUsageInfo());
sb.AppendLine("");
sb.AppendLine("Examples:");
sb.AppendLine("");
sb.AppendLine(" abp new generate-proxy -t ng");
sb.AppendLine(" abp new Acme.BookStore -t js -m identity -o Pages/Identity/client-proxies.js");
sb.AppendLine(" abp new Acme.BookStore -t csharp --folder MyProxies/InnerFolder");
return sb.ToString();
}
public override string GetShortDescription()
{
return "Generates Angular service proxies and DTOs to consume HTTP APIs.";
return "Generates client service proxies and DTOs to consume HTTP APIs.";
}
}
}

37
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProxyCommandBase.cs

@ -66,11 +66,12 @@ namespace Volo.Abp.Cli.Commands
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.ToLower(), url, output, target, apiName, source, commandLineArgs.Options);
return new GenerateProxyArgs(CommandName, workDirectory, module.ToLower(), url, output, target, apiName, source, folder, commandLineArgs.Options);
}
public string GetUsageInfo()
public virtual string GetUsageInfo()
{
var sb = new StringBuilder();
@ -81,11 +82,15 @@ namespace Volo.Abp.Cli.Commands
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("-a|--api-name <module-name> (default: 'default') The name of the API endpoint defined in the /src/environments/environment.ts.");
sb.AppendLine("-s|--source <source-name> (default: 'defaultProject') Angular project name to resolve the root namespace & API definition URL from.");
sb.AppendLine("-o|--output <output-name> (default: 'defaultProject') Angular project name to place generated code in.");
sb.AppendLine("-p|--prompt Asks the options from the command line prompt (for the missing options)");
sb.AppendLine("-m|--module <module-name> (default: 'app') The name of the backend module you wish to generate proxies for.");
sb.AppendLine("-t|--type <generate-type> The name of generate type (csharp, js, ng).");
sb.AppendLine("-wd|--working-directory <directory-path> Execution directory.");
sb.AppendLine("-a|--api-name <module-name> (default: 'default') The name of the API endpoint defined in the /src/environments/environment.ts.");
sb.AppendLine("-s|--source <source-name> (default: 'defaultProject') Angular project name to resolve the root namespace & API definition URL from.");
sb.AppendLine("-o|--output <output-name> JavaScript file path or folder to place generated code in.");
sb.AppendLine("-p|--prompt Asks the options from the command line prompt (for the missing options)");
sb.AppendLine("--target <target-name> (default: 'defaultProject') Angular project name to place generated code in.");
sb.AppendLine("--folder <folder-name> (default: 'ClientProxies') Folder name to place generated CSharp code in.");
sb.AppendLine("");
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI");
@ -102,6 +107,12 @@ namespace Volo.Abp.Cli.Commands
public const string Long = "module";
}
public static class GenerateType
{
public const string Short = "t";
public const string Long = "type";
}
public static class ApiName
{
public const string Short = "a";
@ -113,13 +124,6 @@ namespace Volo.Abp.Cli.Commands
public const string Short = "s";
public const string Long = "source";
}
public static class GenerateType
{
public const string Short = "t";
public const string Long = "type";
}
public static class Output
{
public const string Short = "o";
@ -137,6 +141,11 @@ namespace Volo.Abp.Cli.Commands
public const string Long = "prompt";
}
public static class Folder
{
public const string Long = "folder";
}
public static class Url
{
public const string Long = "url";

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/RemoveProxyCommand.cs

@ -19,7 +19,7 @@ namespace Volo.Abp.Cli.Commands
public override string GetShortDescription()
{
return "Remove Angular service proxies and DTOs to consume HTTP APIs.";
return "Remove client service proxies and DTOs to consume HTTP APIs.";
}
}
}

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxy/Angular/AngularServiceProxyGenerator.cs

@ -38,7 +38,6 @@ namespace Volo.Abp.Cli.ServiceProxy.Angular
var source = args.Source ?? defaultValue;
var target = args.Target ?? defaultValue;
var commandBuilder = new StringBuilder("npx ng g @abp/ng.schematics:" + schematicsCommandName);
if (module != null)

113
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxy/CSharp/CSharpServiceProxyGenerator.cs

@ -6,6 +6,7 @@ using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Volo.Abp.Cli.Commands;
using Volo.Abp.Cli.Http;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Modeling;
@ -17,24 +18,31 @@ namespace Volo.Abp.Cli.ServiceProxy.CSharp
public class CSharpServiceProxyGenerator : ServiceProxyGeneratorBase, ITransientDependency
{
public const string Name = "CSHARP";
public const string UsingPlaceholder = "<using placeholder>";
public const string MethodPlaceholder = "<method placeholder>";
public const string ClassName = "<className>";
public const string ServiceInterface = "<serviceInterface>";
public const string ServicePostfix = "APPSERVICE";
public const string DefaultNamespace = "ClientProxies";
public const string Namespace = "<namespace>";
public readonly string ClientProxyTemplate = "<using placeholder>" +
$"{Environment.NewLine}" +
$"{Environment.NewLine}namespace <namespace>" +
$"{Environment.NewLine}{{" +
$"{Environment.NewLine} public class <className> : ClientProxyBase<<serviceInterface>>, <serviceInterface>" +
$"{Environment.NewLine} {{" +
$"{Environment.NewLine} <method placeholder>" +
$"{Environment.NewLine} }}" +
$"{Environment.NewLine}}}";
private const string UsingPlaceholder = "<using placeholder>";
private const string MethodPlaceholder = "<method placeholder>";
private const string ClassName = "<className>";
private const string ServiceInterface = "<serviceInterface>";
private const string ServicePostfix = "APPSERVICE";
private const string DefaultNamespace = "ClientProxies";
private const string Namespace = "<namespace>";
private readonly string _clientProxyTemplate = "// This file is automatically generated by ABP framework to use MVC Controllers from CSharp" +
$"{Environment.NewLine}<using placeholder>" +
$"{Environment.NewLine}" +
$"{Environment.NewLine}namespace <namespace>" +
$"{Environment.NewLine}{{" +
$"{Environment.NewLine} public partial class <className> : ClientProxyBase<<serviceInterface>>, <serviceInterface>" +
$"{Environment.NewLine} {{" +
$"{Environment.NewLine} <method placeholder>" +
$"{Environment.NewLine} }}" +
$"{Environment.NewLine}}}";
private readonly string _clientProxyPartialTemplate = "// This file is part of <className>, you can customize it here" +
$"{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;",
@ -54,6 +62,13 @@ namespace Volo.Abp.Cli.ServiceProxy.CSharp
public override async Task GenerateProxyAsync(GenerateProxyArgs args)
{
var projectFilePath = CheckWorkDirectory(args.WorkDirectory);
if (args.CommandName == RemoveProxyCommand.Name)
{
RemoveClientProxyFile(args);
return;
}
var projectName = Path.GetFileNameWithoutExtension(projectFilePath);
var assemblyFilePath = Path.Combine(args.WorkDirectory, "bin", "Debug", GetTargetFrameworkVersion(projectFilePath), $"{projectName}.dll");
var startupModule = GetStartupModule(assemblyFilePath);
@ -68,34 +83,46 @@ namespace Volo.Abp.Cli.ServiceProxy.CSharp
{
if (ShouldGenerateProxy(controller.Value))
{
await GenerateClientProxyFile(args, controller.Value, appServiceTypes, startupModule.Namespace);
await GenerateClientProxyFileAsync(args, controller.Value, appServiceTypes, startupModule.Namespace);
}
}
}
protected virtual async Task GenerateClientProxyFile(GenerateProxyArgs args, ControllerApiDescriptionModel controllerApiDescription, List<Type> appServiceTypes, string rootNamespace)
private void RemoveClientProxyFile(GenerateProxyArgs args)
{
var appServiceType = appServiceTypes.FirstOrDefault(x => x.FullName == controllerApiDescription.Interfaces.Last().Type);
var folder = args.Folder.IsNullOrWhiteSpace()? DefaultNamespace : args.Folder;
var folderPath = Path.Combine(args.WorkDirectory, folder);
if (appServiceType == null)
if (Directory.Exists(folderPath))
{
return;
Directory.Delete(folderPath, true);
}
}
var folder = DefaultNamespace;
if (args.ExtraProperties.ContainsKey("--folder"))
private async Task GenerateClientProxyFileAsync(
GenerateProxyArgs args,
ControllerApiDescriptionModel controllerApiDescription,
List<Type> appServiceTypes,
string rootNamespace)
{
var appServiceType = appServiceTypes.FirstOrDefault(x => x.FullName == controllerApiDescription.Interfaces.Last().Type);
if (appServiceType == null)
{
folder = args.ExtraProperties["--folder"];
return;
}
var folder = args.Folder.IsNullOrWhiteSpace()? DefaultNamespace : args.Folder;
var usingNamespaceList = new List<string>(_usingNamespaceList);
var clientProxyName = $"{controllerApiDescription.ControllerName}ClientProxy";
var clientProxyBuilder = new StringBuilder(ClientProxyTemplate);
var clientProxyBuilder = new StringBuilder(_clientProxyTemplate);
var fileNamespace = $"{rootNamespace}.{folder.Replace('/', '.')}";
usingNamespaceList.Add($"using {appServiceType.Namespace};");
clientProxyBuilder.Replace(ClassName, clientProxyName);
clientProxyBuilder.Replace(Namespace, $"{rootNamespace}.{folder.Replace('/','.')}");
clientProxyBuilder.Replace(Namespace, fileNamespace);
clientProxyBuilder.Replace(ServiceInterface, appServiceType.Name);
usingNamespaceList.Add($"using {appServiceType.Namespace};");
var methods = appServiceType.GetInterfaces().SelectMany(x => x.GetMethods()).ToList();
methods.AddRange(appServiceType.GetMethods());
@ -125,9 +152,28 @@ namespace Volo.Abp.Cli.ServiceProxy.CSharp
{
await writer.WriteAsync(clientProxyBuilder.ToString());
}
await GenerateClientProxyPartialFileAsync(clientProxyName, fileNamespace, filePath);
}
private async Task GenerateClientProxyPartialFileAsync(string clientProxyName, string fileNamespace, string filePath)
{
var clientProxyBuilder = new StringBuilder(_clientProxyPartialTemplate);
clientProxyBuilder.Replace(ClassName, clientProxyName);
clientProxyBuilder.Replace(Namespace, fileNamespace);
filePath = filePath.Replace(".cs", ".partial.cs");
using (var writer = new StreamWriter(filePath))
{
await writer.WriteAsync(clientProxyBuilder.ToString());
}
}
protected virtual void GenerateMethod(ActionApiDescriptionModel actionApiDescription, MethodInfo method, StringBuilder clientProxyBuilder, List<string> usingNamespaceList)
private void GenerateMethod(
ActionApiDescriptionModel actionApiDescription,
MethodInfo method,
StringBuilder clientProxyBuilder,
List<string> usingNamespaceList)
{
var methodBuilder = new StringBuilder();
@ -162,7 +208,12 @@ namespace Volo.Abp.Cli.ServiceProxy.CSharp
methodBuilder.AppendLine(" }");
}
private void GenerateAsynchronousMethod(ActionApiDescriptionModel actionApiDescription, MethodInfo method, string returnTypeName, StringBuilder methodBuilder, List<string> usingNamespaceList)
private void GenerateAsynchronousMethod(
ActionApiDescriptionModel actionApiDescription,
MethodInfo method,
string returnTypeName,
StringBuilder methodBuilder,
List<string> usingNamespaceList)
{
methodBuilder.AppendLine($"public async {returnTypeName} {method.Name}(<args>)");
@ -202,7 +253,7 @@ namespace Volo.Abp.Cli.ServiceProxy.CSharp
methodBuilder.AppendLine(" }");
}
protected virtual bool ShouldGenerateProxy(ControllerApiDescriptionModel controllerApiDescription)
private bool ShouldGenerateProxy(ControllerApiDescriptionModel controllerApiDescription)
{
if (!controllerApiDescription.Interfaces.Any())
{

4
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxy/GenerateProxyArgs.cs

@ -23,6 +23,8 @@ namespace Volo.Abp.Cli.ServiceProxy
public string Source { get; }
public string Folder { get; }
[NotNull]
public Dictionary<string, string> ExtraProperties { get; set; }
@ -35,6 +37,7 @@ namespace Volo.Abp.Cli.ServiceProxy
string target,
string apiName,
string source,
string folder,
Dictionary<string, string> extraProperties = null)
{
CommandName = Check.NotNullOrWhiteSpace(commandName, nameof(commandName));
@ -45,6 +48,7 @@ namespace Volo.Abp.Cli.ServiceProxy
Target = target;
ApiName = apiName;
Source = source;
Folder = folder;
ExtraProperties = extraProperties ?? new Dictionary<string, string>();
}
}

29
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ServiceProxy/JavaScript/JavaScriptServiceProxyGenerator.cs

@ -2,6 +2,7 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Cli.Commands;
using Volo.Abp.Cli.Http;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.ProxyScripting.Generators.JQuery;
@ -12,8 +13,8 @@ namespace Volo.Abp.Cli.ServiceProxy.JavaScript
public class JavaScriptServiceProxyGenerator : ServiceProxyGeneratorBase, ITransientDependency
{
public const string Name = "JS";
public const string EventTriggerScript = "abp.event.trigger('abp.serviceProxyScriptInitialized');";
public const string DefaultOutput = "wwwroot/client-proxies";
private const string EventTriggerScript = "abp.event.trigger('abp.serviceProxyScriptInitialized');";
private const string DefaultOutput = "wwwroot/client-proxies";
private readonly JQueryProxyScriptGenerator _jQueryProxyScriptGenerator;
@ -30,15 +31,21 @@ namespace Volo.Abp.Cli.ServiceProxy.JavaScript
{
CheckWorkDirectory(args.WorkDirectory);
var applicationApiDescriptionModel = await GetApplicationApiDescriptionModelAsync(args);
var script = RemoveInitializedEventTrigger(_jQueryProxyScriptGenerator.CreateScript(applicationApiDescriptionModel));
var output = $"{args.WorkDirectory}/{DefaultOutput}/{args.Module}-proxy.js";
var output = Path.Combine(args.WorkDirectory, DefaultOutput, $"{args.Module}-proxy.js");
if (!args.Output.IsNullOrWhiteSpace())
{
output = !args.Output.EndsWith(".js") ? $"{Path.GetDirectoryName(args.Output)}/{args.Module}-proxy.js" : args.Output;
output = args.Output.EndsWith(".js") ? Path.Combine(args.WorkDirectory, args.Output) : Path.Combine(args.WorkDirectory, Path.GetDirectoryName(args.Output), $"{args.Module}-proxy.js");
}
if (args.CommandName == RemoveProxyCommand.Name)
{
RemoveProxy(output);
return;
}
var applicationApiDescriptionModel = await GetApplicationApiDescriptionModelAsync(args);
var script = RemoveInitializedEventTrigger(_jQueryProxyScriptGenerator.CreateScript(applicationApiDescriptionModel));
Directory.CreateDirectory(Path.GetDirectoryName(output));
using (var writer = new StreamWriter(output))
@ -47,6 +54,14 @@ namespace Volo.Abp.Cli.ServiceProxy.JavaScript
}
}
private void RemoveProxy(string filePath)
{
if (File.Exists(filePath))
{
File.Delete(filePath);
}
}
private static void CheckWorkDirectory(string directory)
{
if (!Directory.Exists(directory))

16
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxyBase.cs

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Modeling;
@ -6,7 +7,7 @@ using Volo.Abp.Json;
namespace Volo.Abp.Http.Client
{
public class ClientProxyBase<TService>
public class ClientProxyBase<TService> : ITransientDependency
{
public IAbpLazyServiceProvider LazyServiceProvider { get; set; }
@ -15,23 +16,22 @@ namespace Volo.Abp.Http.Client
protected virtual async Task MakeRequestAsync(ActionApiDescriptionModel action, params object[] arguments)
{
await HttpProxyExecuter.MakeRequestAsync(new HttpProxyExecuterContext(action, BuildArguments(action.Name, arguments), typeof(TService)));
await HttpProxyExecuter.MakeRequestAsync(new HttpProxyExecuterContext(action, BuildArguments(action, arguments), typeof(TService)));
}
protected virtual async Task<T> MakeRequestAsync<T>(ActionApiDescriptionModel action, params object[] arguments)
{
return await HttpProxyExecuter.MakeRequestAndGetResultAsync<T>(new HttpProxyExecuterContext(action, BuildArguments(action.Name, arguments), typeof(TService)));
return await HttpProxyExecuter.MakeRequestAndGetResultAsync<T>(new HttpProxyExecuterContext(action, BuildArguments(action, arguments), typeof(TService)));
}
protected virtual Dictionary<string, object> BuildArguments(string methodName, object[] arguments)
protected virtual Dictionary<string, object> BuildArguments(ActionApiDescriptionModel action, object[] arguments)
{
var method = typeof(TService).GetMethod(methodName);
var parameters = action.Parameters.GroupBy(x => x.NameOnMethod).Select(x => x.Key).ToList();
var dict = new Dictionary<string, object>();
var methodParameters = method.GetParameters();
for (var i = 0; i < methodParameters.Length; i++)
for (var i = 0; i < parameters.Count; i++)
{
dict[methodParameters[i].Name] = arguments[i];
dict[parameters[i]] = arguments[i];
}
return dict;

2
framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs

@ -64,7 +64,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
{
var result = (Task)MakeRequestAndGetResultAsyncMethod
.MakeGenericMethod(invocation.Method.ReturnType.GenericTypeArguments[0])
.Invoke(this, new object[] { context });
.Invoke(HttpProxyExecuter, new object[] { context });
invocation.ReturnValue = await GetResultAsync(
result,

Loading…
Cancel
Save