ASP.NET WebAPI - 如何扫描已注册的操作

时间:2014-08-28 10:08:52

标签: c# asp.net asp.net-web-api asp.net-mvc-apiexplorer

我的WebApi中有几个返回HttpResponseMessage的方法。由于响应类型未知,我必须使用类似

之类的东西在HelpPageConfig中注册它们

config.SetActualResponseType(typeof(X), "SomeController", "GetX");

我想使用自定义属性[ActualResponse(typeof(X)]来注册这些属性,其中声明控制器以避免创建一个大型注册表对象,该对象引用一些杂乱的列表中的所有内容。

如何查询配置以获取已注册的控制器和操作及其属性的列表,以便我可以自动调用SetActualResponseType?

1 个答案:

答案 0 :(得分:0)

我已经探索了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);
    }