This commit is contained in:
Sanchime 2022-11-06 23:03:52 +08:00
parent 38821ed87a
commit da759df8a6
3 changed files with 172 additions and 4 deletions

View File

@ -0,0 +1,27 @@
using Dipper.Alioth.Web;
namespace Dipper.Alioth.Extensions;
public static class StartHostExtension
{
/// <summary>
/// 添加监听服务文件夹组件
/// </summary>
/// <param name="host"></param>
/// <returns></returns>
public static StarHost AddWatchServiceFolder(this StarHost host, string path)
{
if (!Directory.Exists(path))
{
throw new DirectoryNotFoundException(path);
}
// 这块地方应当是另一个类的
// 且该类应当依赖注入单例注入至Host主机中
var watcher = new FileSystemWatcher(path);
watcher.EnableRaisingEvents = true;
return host;
}
}

View File

@ -1,3 +1,6 @@
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace Dipper.Alioth.Web;
@ -6,6 +9,134 @@ public class ServiceConvention : IApplicationModelConvention
{
public void Apply(ApplicationModel application)
{
throw new NotImplementedException();
foreach (var controller in application.Controllers)
{
var type = controller.ControllerType;
if (typeof(IService).IsAssignableFrom(type))
{
ConfigureServiceExplorer(controller);
ConfigureSelector(controller);
}
}
}
private static void ConfigureServiceExplorer(ControllerModel controller)
{
controller.ApiExplorer.IsVisible ??= true;
foreach (var action in controller.Actions)
{
action.ApiExplorer.IsVisible ??= true;
}
}
private void ConfigureSelector(ControllerModel controller)
{
RemoveEmptySelectors(controller.Selectors);
if (controller.Selectors.Any(selector => selector.AttributeRouteModel != null))
return;
foreach (var action in controller.Actions)
{
ConfigureSelector(action);
}
}
private static void RemoveEmptySelectors(IList<SelectorModel> selectors)
{
for (var i = selectors.Count - 1; i >= 0; i--)
{
var selector = selectors[i];
if (selector.AttributeRouteModel == null &&
selector.ActionConstraints.Count <= 0 &&
selector.EndpointMetadata.Count <= 0)
{
selectors.Remove(selector);
}
}
}
private void ConfigureSelector(ActionModel action)
{
RemoveEmptySelectors(action.Selectors);
if (action.Selectors.Count <= 0)
AddServiceSelector(action);
else
NormalizeSelectorRoutes(action);
}
private void AddServiceSelector(ActionModel action)
{
var template = new Microsoft.AspNetCore.Mvc.RouteAttribute(GetRouteTemplate(action));
var selector = new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel(template)
};
selector.ActionConstraints.Add(new HttpMethodActionConstraint(new[] { GetHttpMethod(action) }));
action.Selectors.Add(selector);
}
private void NormalizeSelectorRoutes(ActionModel action)
{
foreach (var selector in action.Selectors)
{
if (selector.AttributeRouteModel == null)
{
var template = new Microsoft.AspNetCore.Mvc.RouteAttribute(GetRouteTemplate(action));
selector.AttributeRouteModel = new AttributeRouteModel(template);
}
if (selector.ActionConstraints.OfType<HttpMethodActionConstraint>().FirstOrDefault()?.HttpMethods?.FirstOrDefault() == null)
selector.ActionConstraints.Add(new HttpMethodActionConstraint(new[] { GetHttpMethod(action) }));
}
}
private static string GetRouteTemplate(ActionModel action)
{
if (action.Attributes is { Count: > 0})
{
foreach (var item in action.Attributes)
{
if (item is RouteAttribute attribute)
{
// attribute.Path
return attribute.Name;
}
}
}
var routeTemplate = new StringBuilder();
//routeTemplate.Append("api");
var names = action.Controller.ControllerType.Namespace.Split('.');
if (names.Length > 2)
{
routeTemplate.Append(names[^2]);
}
// Controller
var controllerName = action.Controller.ControllerName;
if (controllerName.EndsWith("Service"))
controllerName = controllerName[0..^7];
routeTemplate.Append($"/{controllerName}");
// Action
var actionName = action.ActionName;
if (actionName.EndsWith("Async"))
actionName = actionName[..^"Async".Length];
if (!string.IsNullOrEmpty(actionName))
routeTemplate.Append($"/{actionName}");
return routeTemplate.ToString();
}
private static string GetHttpMethod(ActionModel action)
{
var actionName = action.ActionName;
return actionName.StartsWith("Get") ? "GET" : "POST";
}
}

View File

@ -6,13 +6,23 @@ namespace Dipper.Alioth.Web;
public class StarHost
{
public static void Run(string[] args, Action<StarOption> action)
private StarHost()
{
}
public StarHost CreateHost()
{
return new StarHost();
}
public void Run(string[] args, Action<StarOption> action)
{
var app = Configure(args, action);
app.Run();
}
public static Task RunAsync(string[] args, Action<StarOption> action)
public Task RunAsync(string[] args, Action<StarOption> action)
{
var app = Configure(args, action);
@ -20,7 +30,7 @@ public class StarHost
}
private static WebApplication Configure(string[] args, Action<StarOption> action)
private WebApplication Configure(string[] args, Action<StarOption> action)
{
var builder = WebApplication.CreateBuilder(args);