172 lines
7.2 KiB
C#
Raw Normal View History

2025-04-24 18:31:27 +08:00
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using System.Web.Http.Routing;
namespace SwashbuckleEx.WebApiTest.Selectors
{
public class ClassifiedHttpControllerSelector:DefaultHttpControllerSelector
{
private const string AreaRouteVariableName = "area";
private const string CategoryRouteVariableName = "category";
private const string TheFixControllerFolderName = "Controllers";
private readonly HttpConfiguration _configuration;
private readonly Lazy<ILookup<string, Type>> _apiControllerTypes;
private ILookup<string, Type> ApiControllerTypes;
public ClassifiedHttpControllerSelector(HttpConfiguration configuration) : base(configuration)
{
_configuration = configuration;
_apiControllerTypes=new Lazy<ILookup<string, Type>>(GetApiControllerTypes);
}
public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
//return GetApiController(request);
HttpControllerDescriptor des = null;
string controllerName = this.GetControllerName(request);
if (!string.IsNullOrWhiteSpace(controllerName))
{
var groups = this.ApiControllerTypes[controllerName.ToLower()];
if (groups != null && groups.Any())
{
string endString;
var routeDic = request.GetRouteData().Values;//存在controllerName的必定取到IHttpRouteData
if (routeDic.Count > 1)
{
StringBuilder sb=new StringBuilder();
foreach (var key in routeDic.Keys)
{
sb.Append(".");
sb.Append(routeDic[key]);
if (key.Equals(DefaultHttpControllerSelector.ControllerSuffix,
StringComparison.CurrentCultureIgnoreCase))
{
//如果是Control则代表命名空间结束
break;
}
}
sb.Append(DefaultHttpControllerSelector.ControllerSuffix);
endString = sb.ToString();
}
else
{
endString = string.Format(".{0}{1}", controllerName,
DefaultHttpControllerSelector.ControllerSuffix);
}
// 取NameSpace节点数最少的类型
var type =
groups.Where(t => t.FullName.EndsWith(endString, StringComparison.CurrentCultureIgnoreCase))
.OrderBy(t => t.FullName.Count(s => s == '.'))
.FirstOrDefault();//默认返回命名空间节点数最少的第一
if (type != null)
{
des=new HttpControllerDescriptor(this._configuration,controllerName,type);
}
}
}
if (des == null)
{
throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
string.Format("No route providing a controller name was found to match request URI '{0}'",
request.RequestUri)));
}
return des;
}
private static string GetRouteValueByName(HttpRequestMessage request, string routeName)
{
IHttpRouteData data = request.GetRouteData();
if (data.Values.ContainsKey(routeName))
{
return data.Values[routeName] as string;
}
return null;
}
//private static ConcurrentDictionary<string, Type> GetAllControllerTypes()
//{
// Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
// Dictionary<string, Type> types =
// assemblies.SelectMany(
// x =>
// x.GetTypes()
// .Where(
// t =>
// !t.IsAbstract &&
// t.Name.EndsWith(ControllerSuffix, StringComparison.OrdinalIgnoreCase) &&
// typeof(IHttpController).IsAssignableFrom(t))).ToDictionary(t => t.FullName, t => t);
// return new ConcurrentDictionary<string, Type>(types);
//}
private ILookup<string, Type> GetApiControllerTypes()
{
IAssembliesResolver assembliesResolver = this._configuration.Services.GetAssembliesResolver();
return
this._configuration.Services.GetHttpControllerTypeResolver()
.GetControllerTypes(assembliesResolver)
.ToLookup(
t =>
t.Name.ToLower()
.Substring(0, t.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length),
t => t);
}
//private HttpControllerDescriptor GetApiController(HttpRequestMessage request)
//{
// string areaName = GetRouteValueByName(request, AreaRouteVariableName);
// string categoryName = GetRouteValueByName(request, CategoryRouteVariableName);
// string controllerName = GetControllerName(request);
// Type type;
// try
// {
// type = GetControllerType(areaName, categoryName, controllerName);
// }
// catch (Exception)
// {
// return null;
// }
// return new HttpControllerDescriptor(_configuration,controllerName,type);
//}
//private Type GetControllerType(string areaName, string categoryName, string controllerName)
//{
// IEnumerable<KeyValuePair<string, Type>> query = _apiControllerTypes.Value.AsEnumerable();
// string controllerSearchingName;
// if (string.IsNullOrEmpty(areaName))
// {
// controllerSearchingName = TheFixControllerFolderName + "." + controllerName;
// }
// else
// {
// if (string.IsNullOrEmpty(categoryName))
// {
// controllerSearchingName = TheFixControllerFolderName + "." + areaName + "." + controllerName;
// }
// else
// {
// controllerSearchingName = TheFixControllerFolderName + "." + areaName + "." + categoryName + "." +
// controllerName;
// }
// }
// return
// query.Where(x => x.Key.IndexOf(controllerSearchingName, StringComparison.OrdinalIgnoreCase) != -1)
// .Select(x => x.Value)
// .SingleOrDefault();
//}
}
}