using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
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
{
///
/// WebApi区域控制器选择器
///
public class AreaHttpControllerSelector : DefaultHttpControllerSelector
{
///
/// 区域路由变量名
///
private const string AreaRouteVariableName = "area";
///
/// Http配置
///
private readonly HttpConfiguration _configuration;
///
/// Api控制器类型字典
///
private readonly Lazy> _apiControllerTypes;
///
/// 初始化一个类型的实例
///
/// Http配置
public AreaHttpControllerSelector(HttpConfiguration configuration) : base(configuration)
{
_configuration = configuration;
_apiControllerTypes = new Lazy>(GetControllerTypes);
}
///
/// 获取控制器类型字典
///
///
private static ConcurrentDictionary GetControllerTypes()
{
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
Dictionary types = assemblies
.SelectMany(a => a
.GetTypes().Where(t =>
!t.IsAbstract &&
t.Name.EndsWith(ControllerSuffix, StringComparison.OrdinalIgnoreCase) &&
typeof(IHttpController).IsAssignableFrom(t)))
.ToDictionary(t => t.FullName, t => t);
return new ConcurrentDictionary(types);
}
///
/// 由Http请求获取控制台描述信息
///
/// Http请求消息
///
public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
return GetApiController(request);
}
///
/// 获取Api控制器
///
/// Http请求消息
///
private HttpControllerDescriptor GetApiController(HttpRequestMessage request)
{
string areaName = GetAreaName(request);
string controllerName = GetControllerName(request);
if (controllerName == null)
{
throw new InvalidOperationException("获取的Api控制器名称为空");
}
Type type = GetControllerType(areaName, controllerName);
return new HttpControllerDescriptor(_configuration, controllerName, type);
}
///
/// 获取区域名
///
/// Http请求消息
///
private static string GetAreaName(HttpRequestMessage request)
{
IHttpRouteData data = request.GetRouteData();
object areaName;
if (data.Route == null || data.Route.DataTokens == null)
{
if (data.Values.TryGetValue(AreaRouteVariableName, out areaName))
{
return areaName.ToString();
}
return null;
}
return data.Route.DataTokens.TryGetValue(AreaRouteVariableName, out areaName) ? areaName.ToString() : null;
}
///
/// 获取控制器类型
///
/// 区域名
/// 控制器名
///
private Type GetControllerType(string areaName, string controllerName)
{
IEnumerable> query = _apiControllerTypes.Value.AsEnumerable();
query = string.IsNullOrWhiteSpace(areaName) ? query.WithoutAreaName() : query.ByAreaName(areaName);
Type type = query.ByControllerName(controllerName).Select(m => m.Value).SingleOrDefault();
if (type == null)
{
throw new Exception(string.Format("未找到名称为“{0}”的Api控制器",controllerName));
}
return type;
}
}
}