2012-10-22 9 views
11

Wenn ich eine Dependency Injection für ASP.NET MVC-Controller implementieren möchten, kann ich IControllerFactory Schnittstelle verwenden, um eine Factory-Klasse zu erstellen und registrieren sie dann in Global.asax.cs, wie:Gibt es einen HttpControllerBuilder für die ASP.NET-Web-API?

ControllerBuilder.Current.SetControllerFactory(controllerFactory) 

(Referenz: http://www.dotnetcurry.com/ShowArticle.aspx?ID=786)

Nun meine Frage:

Wie könnte ich eine Fabrik für eine IHttpControllerActivator abgeleiteten Klasse festgelegt?

Haben wir etwas in ASP.NET MVC 4.0 wie haben:

HttpControllerBuilder.Current.SetApiControllerActivator(httpControllerActivator) 

?


Update:

ich meine aktuellen Code hinzufügen möchten, könnte es hilfreich sein, den Fall zu verstehen:

Meine maßgeschneiderte 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; 
    } 
} 

Meine Komposition Wurzel:

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

Schließlich ist dies in meinem Global.asax.cs, wo ich einen Trick benötigen:

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

Antwort

8

Mark Seemann, den Autor von Dependency Injection in .NET, eine kurze Serie auf DI mit ASP.NET WebAPI hat.

Er legt die Zusammensetzung Wurzel innerhalb eines IHttpControllerActivator

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

Vielleicht, das hilft.


aktualisieren

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

Register Ihre benutzerdefinierten HttpControllerActivator global.

+0

Aus welchem ​​Grund wird die Create-Methode nicht ausgelöst? Ich kehre eine generische Controller 'Öffentliche IHttpController erstellen ( HttpRequestMessage Anfrage, HttpControllerDescriptor controllerDescriptor, Typ _controllerType) {return (IHttpController) neuer GenericApiController (); } ' – Bellash

1

In ASP.NET Web API HttpControllerDispatcher für den Bau von Steuerungen verantwortlich ist. Es funktioniert standardmäßig mit dem DependecyResolver, aber wenn Sie seine Funktionalität erweitern möchten, müssen Sie die SendAsync-Methode überschreiben und sie erneut registrieren.

Beispiel:

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

Hinweis:

Allerdings war ich nicht in der Lage eine elegante Art und Weise zu finden, den Standard eine global zu ersetzen. Sie können die Standardroute für jede Route problemlos durch ersetzen, indem Sie diesen benutzerdefinierten Dispatcher an eine Route anhängen, aber es scheint keine Möglichkeit zu geben, dies global zu tun. Ich öffnete eine Diskussion auf, dass bei der Projekt-Site ein: http://aspnetwebstack.codeplex.com/discussions/400366

Verwandte Themen