2012-10-22 65 views
11

如果我要实现对ASP.NET MVC控制器依赖注入,我可以用IControllerFactory界面来创建一个工厂类,然后在Global.asax.cs中进行注册,如:是否有任何ASP.NET Web API的HttpControllerBuilder?

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); 
    } 

回答

8

马克西曼,在.NET依赖注入的作者,对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全球。

+0

为什么'Create'方法不会触发?我回一个通用控制器'公共IHttpController创建( HttpRequestMessage要求, HttpControllerDescriptor controllerDescriptor, 类型_controllerType) {回报(IHttpController)新GenericApiController (); }' – Bellash

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