C#Web Api中的动态寄存器控制器

MAG*_*Gx2 4 c# asp.net-web-api

tl; dr:我正在创建Type(通过反射)正在扩展ApiController.如何动态注册它(它可以在启动时注册;无需在运行时执行此操作).

很长的故事:

所以在我的应用程序中我有多个接口,即:

interface IMyInterface
{
    MyResponse Hello(MyRequest request);
}
Run Code Online (Sandbox Code Playgroud)

我想要实现的是每个接口创建控制器应该如下所示:

public class IMyInterfaceController : ApiController
{
    public IMyInterface MyInterface { get; set; }

    public MyResponse Hello([FromBody] MyRequest request)
    {
        return MyInterface.Hello(request);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用大量C#反射已经完成了生成此控制器.我现在要做的就是注册这个控制器/api/{controller}/{action}.

Global.asax现在,我得到这个:

public class MvcApplication : System.Web.HttpApplication
{
    private readonly InterfaceReader _reader = new InterfaceReader(); // this class is doing all staff with reflection to create controller class

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);

        var controller = _reader.CreateController(new MyImplementation()); // MuImplementation implements IMyInterface
    }
}
Run Code Online (Sandbox Code Playgroud)

Ant*_*ton 5

解决方案 IHttpControllerFactory

我想你需要的是一个控制器工厂:

public class MyHttpControllerFactory : IHttpControllerFactory
{
    private readonly InterfaceReader _reader;
    private readonly HttpConfiguration _configuration;

    public MyHttpControllerFactory(InterfaceReader reader, HttpConfiguration configuration)
    {
        _reader = reader;
        _configuration = configuration;
    }

    public IHttpController CreateController(HttpControllerContext controllerContext, string controllerName)
    {
        if (controllerName == null)
        {
            throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", controllerContext.Request.RequestUri.AbsolutePath));
        }

        // Change the line below to whatever suits your needs.
        var controller = _reader.CreateController(new MyImplementation());
        controllerContext.Controller = controller;
        controllerContext.ControllerDescriptor = new HttpControllerDescriptor(configuration, controllerName, controller.GetType());

        return controllerContext.Controller;
    }

    public void ReleaseController(IHttpController controller)
    {
        // You may want to be able to release the controller as well.
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在Global.asax您需要注册自定义控制器工厂:

public class MvcApplication : System.Web.HttpApplication
{
    private readonly InterfaceReader _reader = new InterfaceReader(); // this class is doing all staff with reflection to create controller class

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);

        GlobalConfiguration.Configuration.ServiceResolver.SetService(typeof(IHttpControllerFactory), new MyHttpControllerFactory(_reader, GlobalConfiguration.Configuration));
    }
}
Run Code Online (Sandbox Code Playgroud)

解决方案 IHttpControllerActivator

如果您使用Web Api 2,那么解决方案是使用IDependencyResolverIHttpControllerActivator代替工厂.我想IHttpControllerActivator在你的情况下这是更好的选择.

public class MyServiceActivator : IHttpControllerActivator
{
    private readonly InterfaceReader _reader;
    private readonly HttpConfiguration _configuration;

    public MyServiceActivator(InterfaceReader reader, HttpConfiguration configuration)
    {
        _reader = reader;
        _configuration = configuration;
    }

    public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
    {
        // Change the line below to whatever suits your needs.
        var controller = _reader.CreateController(new MyImplementation());
        return controller;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在Global.asax您需要注册自定义激活器:

public class MvcApplication : System.Web.HttpApplication
{
    // this class is doing all staff with reflection to create controller class
    private readonly InterfaceReader _reader = new InterfaceReader();

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);

        HttpConfiguration config = GlobalConfiguration.Configuration;
        config.Services.Replace(typeof(IHttpControllerActivator), new MyServiceActivator(_reader, config));
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助.