ASP.NET WebAPI - Как сканировать зарегистрированные действия
У меня есть несколько методов в моем WebApi, которые возвращают HttpResponseMessage. Поскольку тип ответа неизвестен, я должен зарегистрировать их в HelpPageConfig, используя что-то вроде
config.SetActualResponseType(typeof(X), "SomeController", "GetX");
Я хотел бы зарегистрировать их, используя пользовательский атрибут [ActualResponse(typeof(X)]
где контроллер объявлен, чтобы избежать создания большого объекта реестра, который ссылается на все в немного запутанном списке.
Как я могу запросить конфигурацию, чтобы получить список зарегистрированных контроллеров и действий и их атрибутов, чтобы я мог автоматически вызывать SetActualResponseType?
1 ответ
Я исследовал источники mvc и web api и не нашел места, где можно внедрить такую логику. Поиск методов действия в mvc/web api - непростая задача, поскольку существует ряд проверок, которые определяют, является ли метод методом действия или обычным методом (на основе зарегистрированных маршрутов и т. Д.). В вашем случае вам нужно обрабатывать только методы с вашим пользовательским атрибутом ActualResponse, верно? Так что вы можете сделать это с отражением. Конечно, такие вещи не быстрые и приносят некоторый удар по производительности. Но если вы запускаете такую логику один раз в Application_Start, я думаю, что это приемлемо.
Пример реализации:
public static class ActionMethodsRegistrator
{
private static readonly Type ApiControllerType = typeof(IHttpController);
public static void RegisterActionMethods(YourCustomConfig config)
{
// find all api controllers in executing assembly
var contollersTypes = Assembly.GetExecutingAssembly().GetTypes()
.Where(foundType => ApiControllerType.IsAssignableFrom(foundType));
// you may also search for controllers in all loaded assemblies e.g.
// var contollersTypes = AppDomain.CurrentDomain.GetAssemblies()
// .SelectMany(s => s.GetTypes())
// .Where(foundType => ApiControllerType.IsAssignableFrom(foundType));
foreach (var contollerType in contollersTypes)
{
// you may add more restriction here for optimization, e. g. BindingFlags.DeclaredOnly
// I took search parameters from mvc/web api sources.
var allMethods = contollerType.GetMethods(BindingFlags.Instance | BindingFlags.Public);
foreach (var methodInfo in allMethods)
{
var actualResponseAttrubute = methodInfo.GetCustomAttribute<ActualResponseAttribute>();
if (actualResponseAttrubute != null)
{
config.SetActualResponseType(actualResponseAttrubute.Type, contollerType.Name, methodInfo.Name);
}
}
}
}
}
Файл Global.asax:
protected void Application_Start()
{
//....
YourCustomConfig config = InitializeConfig();
ActionMethodsRegistrator.RegisterActionMethods(config);
}