【问题标题】:Is there any HttpControllerBuilder for ASP.NET Web API?是否有任何用于 ASP.NET Web API 的 HttpControllerBuilder?
【发布时间】:2015-02-19 07:33:18
【问题描述】:

如果我想为 ASP.NET MVC 控制器实现依赖注入,我可以使用IControllerFactory 接口创建一个工厂类,然后在 Global.asax.cs 中注册它,例如:

ControllerBuilder.Current.SetControllerFactory(controllerFactory)

(参考:http://www.dotnetcurry.com/ShowArticle.aspx?ID=786

现在我的问题是:

如何为IHttpControllerActivator 派生类设置工厂?

我们在 ASP.NET MVC 4.0 中是否有类似的东西:

HttpControllerBuilder.Current.SetApiControllerActivator(httpControllerActivator)

?


更新:

我想添加我当前的代码,这可能有助于理解案例:

我自定义的 HttpControllerActivator:

public class MyCustomApiActivator : DefaultHttpControllerActivator 
                                    //or IHttpControllerActivator ?
{
    private readonly Dictionary<string, Func<HttpRequestMessage, IHttpController>> _apiMap;

    public MyCustomApiActivator(IMyRepository repository)
    {
        if (repository == null)
        {
            throw new ArgumentException("repository");
        }
        _apiMap = new Dictionary<string, Func<HttpRequestMessage, IHttpController>>();
        controllerMap["Home"] = context => new HomeController();
        _apiMap["MyCustomApi"] = context => new MyCustomApiController(repository);
    }

    public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
    {
        if(_apiMap.ContainsKey(controllerType.Name))
            return _apiMap[controllerType.Name](request);
        return null;
    }
}

我的作文根:

public class CompositionRoot
{
    private readonly IHttpControllerActivator _apiControllerActivator;

    public CompositionRoot()
    {
        _apiControllerActivator = CompositionRoot.CreateHttpControllerActivator();
    }

    public IHttpControllerActivator ApiControllerActivator
    {
        get { return _apiControllerActivator; }
    }

    private static IHttpControllerActivator CreateHttpControllerActivator()
    {
        string defaultRepositoryTypeName = ConfigurationManager.AppSettings["DefaultRepositoryTypeName"];
        var defaultRepositoryType = Type.GetType(defaultRepositoryTypeName, true);
        var defaultRepository = (IMyRepository)Activator.CreateInstance(defaultRepositoryType);

        var apiController = new MyCustomApiActivator(defaultRepository);
        return apiController;
    }
}

最后这是我的Global.asax.cs,我需要一个技巧:

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

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


        var root = new CompositionRoot();
        //The following line raise this compile-time error:
        // cannot convert from 'System.Web.Http.Dispatcher.IHttpControllerActivator' 
        //                to 'System.Web.Mvc.IControllerFactory'
        ControllerBuilder.Current.SetControllerFactory(root.ApiControllerActivator);
    }

【问题讨论】:

    标签: dependency-injection asp.net-mvc-4 asp.net-web-api


    【解决方案1】:

    .NET 中的依赖注入一书的作者 Mark Seemann 有一个关于 DI 与 ASP.NET WebAPI 的简短系列。

    他将组合根放在IHttpControllerActivator

    1. Dependency Injection and Lifetime Management with ASP.NET Web API
    2. Dependency Injection in ASP.NET Web API with Castle Windsor

    也许这有帮助。


    更新

    GlobalConfiguration.Configuration.Services.Replace(
      typeof(IHttpControllerActivator),
      new PoorMansCompositionRoot());
    

    在全球范围内注册您的自定义HttpControllerActivator

    【讨论】:

    • Create 方法不触发的原因是什么?我返回一个通用控制器public IHttpController Create( HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type _controllerType) { return (IHttpController)new GenericApiController&lt;TView&gt;(); }
    【解决方案2】:

    在 ASP.NET Web API 中HttpControllerDispatcher 负责构造控制器。默认情况下它与 DependecyResolver 一起工作,但如果你想扩展它的功能,你需要重写它的 SendAsync 方法并重新注册。

    例子:

    public class MyCustomDispatcher : HttpControllerDispatcher {
    
        protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, 
            CancellationToken cancellationToken) {
    
            // Do your stuff here
    
            // According to your requirements, either run its default functionality 
            // or return your own stuff
            return base.SendAsync(request, cancellationToken);
        }
    }
    

    注意:

    但是,我无法找到一种优雅的方式来替换默认方式 全球范围内。您可以通过以下方式轻松替换默认的每条路线 将此自定义调度程序附加到路线,但似乎没有 在全球范围内做到这一点的方法。我在 项目地址:http://aspnetwebstack.codeplex.com/discussions/400366

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-11
      • 2018-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-23
      • 1970-01-01
      相关资源
      最近更新 更多