是否有适用于ASP.NET Web API的HttpControllerBuilder?

时间:2012-10-22 19:29:07

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

如果我想为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);
    }

2 个答案:

答案 0 :(得分:9)

Mark Seemann,.NET中的Dependency Injection的作者,有一篇关于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
  3. 也许这有帮助。


    <强>更新

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

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

答案 1 :(得分:1)

在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