2013-06-25 46 views
7

Tôi có một dịch vụ được sử dụng bởi một vài bộ điều khiển trong dự án WebAPI của tôi. Dịch vụ cần tạo URL, vì vậy, lý tưởng là nó sẽ nhận được một thông số hàm xây dựng UrlHelper.Tiêm WebAPI UrlGelper vào dịch vụ bằng cách sử dụng Autofac

public class MyService 
{ 
    public MyService(UrlHelper urlHelper) { ... } 
} 

Tôi đang sử dụng Autofac làm vùng chứa IoC của mình. Làm cách nào để đăng ký UrlHelper trong vùng chứa? Nó cần một HttpRequestMessage và tôi không thể tìm ra cách để có được thông báo "hiện tại".

+0

Hãy nhìn vào những gì chúng tôi đã làm việc trên cho WebAPIBook, nó có một giải pháp khả thi cho vấn đề này ... https://gist.github.com/glennblock/8f18bdee15eec9c1af70 –

+0

Ah, vâng, rất hay. Tôi đã suy nghĩ về việc tạo ra một trình xử lý tin nhắn để giải quyết điều này :) Tôi sẽ cung cấp cho nó một shot. Cảm ơn. –

Trả lời

6

Sử dụng phương pháp RegisterHttpRequestMessage đăng ký yêu cầu hiện tại và sau đó bạn cũng có thể đăng ký các helper URL như vậy:

public static IContainer SetupContainer(HttpConfiguration config) 
{ 
    var containerBuilder = new ContainerBuilder(); 

    // Register your Web API. 
    containerBuilder.RegisterApiControllers(Assembly.GetExecutingAssembly()); 
    containerBuilder.RegisterHttpRequestMessage(config); 
    containerBuilder.Register(x => new UrlHelper(x.Resolve<HttpRequestMessage>())); 
    containerBuilder.RegisterWebApiFilterProvider(config); 
    containerBuilder.RegisterWebApiModelBinderProvider(); 

    // Register your other types... 

    var container = containerBuilder.Build(); 

    // Set the dependency resolver to be Autofac. 
    config.DependencyResolver = new AutofacWebApiDependencyResolver(container); 

    return container; 
} 
+0

Autowiring các thuộc tính điều khiển api không làm việc với RegisterHttpRequestMessage. tức là RegisterApiControllers (Assembly.GetExecutingAssembly()). PropertiesAutowired(). Nếu bạn sử dụng mã này, bạn sẽ mất tùy chọn để tự động sửa lỗi. – Mick

0

tốt nhất tôi có thể nghĩ đến là làm cho dịch vụ của bạn thực hiện IAutofacActionFilter như vậy

public class MyService : IAutofacActionFilter 
    { 
     private UrlHelper _urlHelper; 

     public void DoSomething() 
     { 
      var link = Url.Link("SomeRoute", new {}); 
     } 

     private UrlHelper Url 
     { 
      get 
      { 
       if(_urlHelper == null) 
        throw new InvalidOperationException(); 

       return _urlHelper; 
      } 
     } 

     public void OnActionExecuted(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext) 
     {    
     } 

     public void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) 
     { 
      this._urlHelper = actionContext.Request.GetUrlHelper(); 
     } 
    } 

và sau đó sử dụng một cái gì đó giống như cấu hình Autofac sau

builder.RegisterType<MyService>() 
       .AsWebApiActionFilterFor<SomeController>() 
       .AsSelf() 
       .InstancePerApiRequest(); 
4

Dựa trên nhận xét Darrel Miller, tôi đã tạo ra sau :

Lớp chứa đơn giản để giữ tham chiếu đến "hiện tại" HttpRequestMessage

public class CurrentRequest 
{ 
    public HttpRequestMessage Value { get; set; } 
} 

Một handler thông điệp rằng sẽ lưu trữ các yêu cầu hiện tại

public class CurrentRequestHandler : DelegatingHandler 
{ 
    protected async override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) 
    { 
     var scope = request.GetDependencyScope(); 
     var currentRequest = (CurrentRequest)scope.GetService(typeof(CurrentRequest)); 
     currentRequest.Value = request; 
     return await base.SendAsync(request, cancellationToken); 
    } 
} 

Trong Global.asax, khi cấu hình WebAPI, thêm xử lý tin nhắn.

GlobalConfiguration.Configuration.MessageHandlers.Insert(0, new CurrentRequestHandler()); 

Sau đó, cấu hình container Autofac để cho nó xây dựng UrlHelper, nhận được yêu cầu hiện tại từ đối tượng CurrentRequest.

var builder = new ContainerBuilder(); 
builder.RegisterType<CurrentRequest>().InstancePerApiRequest(); 
builder.Register(c => new UrlHelper(c.Resolve<CurrentRequest>().Value)); 
builder.RegisterType<MyService>(); 
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); 
... 
container = builder.Build(); 

UrlHelper sau đó có thể được tiêm vào MyService giống như bất kỳ phụ thuộc khác.

Nhờ Darrel đã chỉ cho tôi đúng hướng.

+8

Tôi vừa thêm hỗ trợ cho sự phụ thuộc của HttpRequestMessage vào Autofac.WebApi và nó sẽ được đưa vào bản phát hành kế tiếp. https://code.google.com/p/autofac/source/detail?r=60d369499963b89224c1f682cfbf8592eae95342 –

+0

tôi không thể có được RegisterHttpRequestMessage làm việc tuy nhiên mã này đã làm công việc – Mick