diff --git a/Plus.AutoApi/IAutoApi.cs b/Plus.AutoApi.Core/IAutoApi.cs
similarity index 59%
rename from Plus.AutoApi/IAutoApi.cs
rename to Plus.AutoApi.Core/IAutoApi.cs
index 42300b0..47ddc45 100644
--- a/Plus.AutoApi/IAutoApi.cs
+++ b/Plus.AutoApi.Core/IAutoApi.cs
@@ -1,4 +1,4 @@
-namespace Plus.AutoApi
+namespace Plus.AutoApi.Core
{
public interface IAutoApi
{
diff --git a/Plus.AutoApi.Core/Plus.AutoApi.Core.csproj b/Plus.AutoApi.Core/Plus.AutoApi.Core.csproj
new file mode 100644
index 0000000..dbdcea4
--- /dev/null
+++ b/Plus.AutoApi.Core/Plus.AutoApi.Core.csproj
@@ -0,0 +1,7 @@
+
+
+
+ netstandard2.0
+
+
+
diff --git a/Plus.AutoApi/Attributes/AutoApiAttribute.cs b/Plus.AutoApi/Attributes/AutoApiAttribute.cs
index 6be609f..8f75718 100644
--- a/Plus.AutoApi/Attributes/AutoApiAttribute.cs
+++ b/Plus.AutoApi/Attributes/AutoApiAttribute.cs
@@ -9,5 +9,7 @@ public class AutoApiAttribute : Attribute
public string AreaName { get; set; }
public bool Disabled { get; set; } = false;
+
+ public bool Inherited { get; set; } = true;
}
}
\ No newline at end of file
diff --git a/Plus.AutoApi/AutoApiControllerFeatureProvider.cs b/Plus.AutoApi/AutoApiControllerFeatureProvider.cs
index 43d5be7..b553790 100644
--- a/Plus.AutoApi/AutoApiControllerFeatureProvider.cs
+++ b/Plus.AutoApi/AutoApiControllerFeatureProvider.cs
@@ -2,6 +2,7 @@
using Plus.AutoApi.Attributes;
using Plus.AutoApi.Helpers;
using System.Reflection;
+using Plus.AutoApi.Core;
namespace Plus.AutoApi
{
diff --git a/Plus.AutoApi/AutoApiConvention.cs b/Plus.AutoApi/AutoApiConvention.cs
index 0ec9170..a023118 100644
--- a/Plus.AutoApi/AutoApiConvention.cs
+++ b/Plus.AutoApi/AutoApiConvention.cs
@@ -1,13 +1,13 @@
-using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Linq;
+using System.Reflection;
+using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Plus.AutoApi.Attributes;
using Plus.AutoApi.Extensions;
using Plus.AutoApi.Helpers;
-using System;
-using System.Linq;
-using System.Reflection;
namespace Plus.AutoApi
{
@@ -22,7 +22,7 @@ public void Apply(ApplicationModel application)
if (typeof(IAutoApi).GetTypeInfo().IsAssignableFrom(type))
{
- controller.ControllerName = controller.ControllerName.RemoveSuffix(PlusConsts.ControllerSuffixes.ToArray());
+ controller.ControllerName = GetRestFulControllerName(controller.ControllerName);
ConfigureArea(controller, attribute);
@@ -43,7 +43,9 @@ public void Apply(ApplicationModel application)
private void ConfigureArea(ControllerModel controller, AutoApiAttribute attribute)
{
if (attribute == null)
+ {
throw new ArgumentException(nameof(attribute));
+ }
if (!controller.RouteValues.ContainsKey("area"))
{
@@ -60,35 +62,38 @@ private void ConfigureArea(ControllerModel controller, AutoApiAttribute attribut
private void ConfigureAutoApi(ControllerModel controller, AutoApiAttribute attribute)
{
- ConfigureApiExplorer(controller);
+ ConfigureApiExplorer(controller, attribute);
ConfigureSelector(controller, attribute);
ConfigureParameters(controller);
}
- private void ConfigureApiExplorer(ControllerModel controller)
+ private void ConfigureApiExplorer(ControllerModel controller, AutoApiAttribute attribute)
{
if (string.IsNullOrEmpty(controller.ApiExplorer.GroupName))
{
controller.ApiExplorer.GroupName = controller.ControllerName;
}
- if (controller.ApiExplorer.IsVisible == null)
- {
- controller.ApiExplorer.IsVisible = true;
- }
+ controller.ApiExplorer.IsVisible ??= true;
foreach (var action in controller.Actions)
{
- ConfigureApiExplorer(action);
+ ConfigureApiExplorer(action, attribute);
}
}
- private void ConfigureApiExplorer(ActionModel action)
+ private void ConfigureApiExplorer(ActionModel action, AutoApiAttribute attribute)
{
- if (action.ApiExplorer.IsVisible == null)
+ if (!attribute.Inherited)
{
- action.ApiExplorer.IsVisible = true;
+ if (action.ActionMethod.DeclaringType != action.Controller.ControllerType)
+ {
+ action.ApiExplorer.IsVisible = false;
+ return;
+ }
}
+
+ action.ApiExplorer.IsVisible ??= true;
}
private void ConfigureSelector(ControllerModel controller, AutoApiAttribute attribute)
@@ -165,15 +170,18 @@ private void NormalizeSelectorRoutes(string areaName, string controllerName, Act
foreach (var selector in action.Selectors)
{
- selector.AttributeRouteModel = selector.AttributeRouteModel == null ?
- CreateActionRouteModel(areaName, controllerName, action) :
- AttributeRouteModel.CombineAttributeRouteModel(CreateActionRouteModel(areaName, controllerName, action), selector.AttributeRouteModel);
+ selector.AttributeRouteModel = selector.AttributeRouteModel == null
+ ? CreateActionRouteModel(areaName, controllerName, action)
+ : AttributeRouteModel.CombineAttributeRouteModel(
+ CreateActionRouteModel(areaName, controllerName, action), selector.AttributeRouteModel);
}
}
private static string GetHttpVerb(ActionModel action)
{
- var getValueSuccess = PlusConsts.AssemblyAutoApiOptions.TryGetValue(action.Controller.ControllerType.Assembly, out AssemblyAutoApiOptions assemblyAutoApiOptions);
+ var getValueSuccess =
+ PlusConsts.AssemblyAutoApiOptions.TryGetValue(action.Controller.ControllerType.Assembly,
+ out var assemblyAutoApiOptions);
if (getValueSuccess && !string.IsNullOrWhiteSpace(assemblyAutoApiOptions?.HttpVerb))
{
@@ -182,19 +190,32 @@ private static string GetHttpVerb(ActionModel action)
var verbKey = action.ActionName.GetPascalOrCamelCaseFirstWord().ToLower();
- return PlusConsts.HttpVerbs.ContainsKey(verbKey) ? PlusConsts.HttpVerbs[verbKey] : PlusConsts.DefaultHttpVerb;
+ return PlusConsts.HttpVerbs.ContainsKey(verbKey)
+ ? PlusConsts.HttpVerbs[verbKey]
+ : PlusConsts.DefaultHttpVerb;
+ }
+
+ private string GetRestFulControllerName(string controllerName)
+ {
+ controllerName = controllerName.RemoveSuffix(PlusConsts.ControllerSuffixes.ToArray());
+ var name = PlusConsts.GetRestFulControllerName?.Invoke(controllerName);
+ if (!string.IsNullOrWhiteSpace(name))
+ {
+ return name;
+ }
+
+ return controllerName;
}
private string GetRestFulActionName(string actionName)
{
+ actionName = actionName.RemoveSuffix(PlusConsts.ActionSuffixes.ToArray());
var name = PlusConsts.GetRestFulActionName?.Invoke(actionName);
if (name != null)
{
return name;
}
- actionName = actionName.RemoveSuffix(PlusConsts.ActionSuffixes.ToArray());
-
var verbKey = actionName.GetPascalOrCamelCaseFirstWord().ToLower();
if (PlusConsts.HttpVerbs.ContainsKey(verbKey))
{
@@ -202,15 +223,11 @@ private string GetRestFulActionName(string actionName)
{
return "";
}
- else
- {
- return actionName.Substring(verbKey.Length);
- }
- }
- else
- {
- return actionName;
+
+ return actionName.Substring(verbKey.Length);
}
+
+ return actionName;
}
private AttributeRouteModel CreateActionRouteModel(string areaName, string controllerName, ActionModel action)
@@ -223,7 +240,9 @@ private AttributeRouteModel CreateActionRouteModel(string areaName, string contr
private static string GetApiPreFix(ActionModel action)
{
- var getValueSuccess = PlusConsts.AssemblyAutoApiOptions.TryGetValue(action.Controller.ControllerType.Assembly, out AssemblyAutoApiOptions assemblyAutoApiOptions);
+ var getValueSuccess =
+ PlusConsts.AssemblyAutoApiOptions.TryGetValue(action.Controller.ControllerType.Assembly,
+ out var assemblyAutoApiOptions);
if (getValueSuccess && !string.IsNullOrWhiteSpace(assemblyAutoApiOptions?.ApiPrefix))
{
@@ -236,20 +255,18 @@ private static string GetApiPreFix(ActionModel action)
private void ConfigureParameters(ControllerModel controller)
{
foreach (var action in controller.Actions)
+ foreach (var para in action.Parameters)
{
- foreach (var para in action.Parameters)
+ if (para.BindingInfo != null)
{
- if (para.BindingInfo != null)
- {
- continue;
- }
+ continue;
+ }
- if (!TypeHelper.IsPrimitiveExtendedIncludingNullable(para.ParameterInfo.ParameterType))
+ if (!TypeHelper.IsPrimitiveExtendedIncludingNullable(para.ParameterInfo.ParameterType))
+ {
+ if (CanUseFormBodyBinding(action, para))
{
- if (CanUseFormBodyBinding(action, para))
- {
- para.BindingInfo = BindingInfo.GetBindingInfo(new[] { new FromBodyAttribute() });
- }
+ para.BindingInfo = BindingInfo.GetBindingInfo(new[] { new FromBodyAttribute() });
}
}
}
@@ -257,7 +274,8 @@ private void ConfigureParameters(ControllerModel controller)
private bool CanUseFormBodyBinding(ActionModel action, ParameterModel parameter)
{
- if (PlusConsts.FormBodyBindingIgnoredTypes.Any(t => t.IsAssignableFrom(parameter.ParameterInfo.ParameterType)))
+ if (PlusConsts.FormBodyBindingIgnoredTypes.Any(t =>
+ t.IsAssignableFrom(parameter.ParameterInfo.ParameterType)))
{
return false;
}
diff --git a/Plus.AutoApi/AutoApiOptions.cs b/Plus.AutoApi/AutoApiOptions.cs
index 4fca760..f266497 100644
--- a/Plus.AutoApi/AutoApiOptions.cs
+++ b/Plus.AutoApi/AutoApiOptions.cs
@@ -31,6 +31,8 @@ public AutoApiOptions()
public Func GetRestFulActionName { get; set; }
+ public Func GetRestFulControllerName { get; set; }
+
public Dictionary AssemblyAutoApiOptions { get; }
public void Valid()
diff --git a/Plus.AutoApi/AutoApiServiceExtensions.cs b/Plus.AutoApi/AutoApiServiceExtensions.cs
index bf14dbe..ac2fe5c 100644
--- a/Plus.AutoApi/AutoApiServiceExtensions.cs
+++ b/Plus.AutoApi/AutoApiServiceExtensions.cs
@@ -38,6 +38,7 @@ private static IServiceCollection AddAutoApi(this IServiceCollection services, A
PlusConsts.ActionSuffixes = options.RemoveActionSuffixes;
PlusConsts.FormBodyBindingIgnoredTypes = options.FormBodyBindingIgnoredTypes;
PlusConsts.GetRestFulActionName = options.GetRestFulActionName;
+ PlusConsts.GetRestFulControllerName = options.GetRestFulControllerName;
PlusConsts.AssemblyAutoApiOptions = options.AssemblyAutoApiOptions;
var partManager = services.GetSingletonInstanceOrNull();
diff --git a/Plus.AutoApi/Plus.AutoApi.csproj b/Plus.AutoApi/Plus.AutoApi.csproj
index 6e1f5fc..cc9feb4 100644
--- a/Plus.AutoApi/Plus.AutoApi.csproj
+++ b/Plus.AutoApi/Plus.AutoApi.csproj
@@ -1,24 +1,32 @@
-
- netcoreapp3.1
- Plus.AutoApi
- 阿星Plus
- https://meowv.com
- Plus.AutoApi 是一个可以用来动态生成 WebApi 不用写 Controller 的组件
- MIT
- https://meowv.com
- https://github.com/Meowv/Plus.AutoApi
- https://avatars2.githubusercontent.com/u/13010050
- https://github.com/Meowv/Plus.AutoApi
- git
- plus;autoapi;plus.autoapi;
- .NET Core 开发工具包
- 0.1.0
-
+
+ netcoreapp3.1
+ Plus.AutoApi
+ 阿星Plus
+ https://meowv.com
+ Plus.AutoApi 是一个可以用来动态生成 WebApi 不用写 Controller 的组件
+ MIT
+ https://meowv.com
+ https://github.com/Meowv/Plus.AutoApi
+ https://avatars2.githubusercontent.com/u/13010050
+ https://github.com/Meowv/Plus.AutoApi
+ git
+ plus;autoapi;plus.autoapi;
+ .NET Core 开发工具包
+ 0.1.0
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Plus.AutoApi/PlusConsts.cs b/Plus.AutoApi/PlusConsts.cs
index 0b72984..908e23a 100644
--- a/Plus.AutoApi/PlusConsts.cs
+++ b/Plus.AutoApi/PlusConsts.cs
@@ -44,6 +44,8 @@ static PlusConsts()
public static Func GetRestFulActionName { get; set; }
+ public static Func GetRestFulControllerName { get; set; }
+
public static Dictionary AssemblyAutoApiOptions { get; set; }
}
}
\ No newline at end of file
diff --git a/Plus.AutoApi/Properties/launchSettings.json b/Plus.AutoApi/Properties/launchSettings.json
new file mode 100644
index 0000000..ac9bf13
--- /dev/null
+++ b/Plus.AutoApi/Properties/launchSettings.json
@@ -0,0 +1,12 @@
+{
+ "profiles": {
+ "Plus.AutoApi": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "http://localhost:64869"
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plus.AutoApiGenerator/Plus.AutoApiGenerator.csproj b/Plus.AutoApiGenerator/Plus.AutoApiGenerator.csproj
new file mode 100644
index 0000000..9d0704d
--- /dev/null
+++ b/Plus.AutoApiGenerator/Plus.AutoApiGenerator.csproj
@@ -0,0 +1,17 @@
+
+
+
+ netstandard2.0
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+
+
diff --git a/Plus.AutoApiGenerator/ServiceGenerator.cs b/Plus.AutoApiGenerator/ServiceGenerator.cs
new file mode 100644
index 0000000..449bf45
--- /dev/null
+++ b/Plus.AutoApiGenerator/ServiceGenerator.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Text;
+using Plus.AutoApi;
+using Plus.AutoApi.Core;
+
+namespace Plus.AutoApiGenerator
+{
+ [Generator]
+ public class ServiceGenerator : ISourceGenerator
+ {
+ private const string NATIVE_SERVICES_TXT_ADDITIONAL_FILE_NAME = "Services.txt";
+ private static readonly char[] ZeroWhiteSpace = new char[]
+ {
+ '\uFEFF', // ZERO WIDTH NO-BREAK SPACE (U+FEFF)
+ '\u200B', // ZERO WIDTH SPACE (U+200B)
+ };
+ public void Initialize(GeneratorInitializationContext context)
+ {
+
+ }
+
+ public void Execute(GeneratorExecutionContext context)
+ {
+ Debugger.Launch();
+ var nativeMethodsTxtFiles = context.AdditionalFiles
+ .Where(af => string.Equals(Path.GetFileName(af.Path), NATIVE_SERVICES_TXT_ADDITIONAL_FILE_NAME, StringComparison.OrdinalIgnoreCase)).ToList();
+ if (!nativeMethodsTxtFiles.Any())
+ {
+ return;
+ }
+
+ var parseOptions = (CSharpParseOptions)context.ParseOptions;
+
+ foreach (AdditionalText nativeMethodsTxtFile in nativeMethodsTxtFiles)
+ {
+ var nativeMethodsTxt = nativeMethodsTxtFile.GetText(context.CancellationToken);
+ if (nativeMethodsTxt is null)
+ {
+ return;
+ }
+
+ foreach (TextLine line in nativeMethodsTxt.Lines)
+ {
+ context.CancellationToken.ThrowIfCancellationRequested();
+ string name = line.ToString();
+ if (string.IsNullOrWhiteSpace(name) || name.StartsWith("//", StringComparison.InvariantCulture))
+ {
+ continue;
+ }
+
+ name = name.Trim().Trim(ZeroWhiteSpace);
+ var location = Location.Create(nativeMethodsTxtFile.Path, line.Span, nativeMethodsTxt.Lines.GetLinePositionSpan(line.Span));
+
+ context.AddSource(name, $"public class {name}{{}}");
+ }
+ }
+ }
+ }
+}