2011-10-21 17 views
16

Więc utknąłem podczas próby uzyskania mojej usługi sieci web ASMX, aby użyć iniekcji zależności i przy użyciu IoC, aby to zrobić. Chcę, aby moja usługa sieciowa mogła korzystać z moich wewnętrznych usług warstwy biznesowej. Usługa internetowa ma być używana przez klienta zewnętrznego z innej domeny i będzie głównie używana do wysyłania i otrzymywania informacji o takich podmiotach, jak Zamówienia i Klienci.Wtyczka ASMX Dependency Injection i IoC

Przykładem może być:

public class MyService : System.Web.Services.WebService 
{ 
    [WebMethod] 
    public string HelloWorld() 
    { 
     return new MyBusinessService().MyMethod(); 
    } 
} 

public class MyBusinessService : IMyBusinessService 
{ 
    public string MyMethod() 
    { 
     return "hello"; 
    } 
} 

Chcę używać iniekcji zależność, aby wyeliminować potrzebę „newing” moje usługi, ale nie mogę znaleźć sposób, aby to zrobić. Mogę go użyć do pracy z biednym mężem DI, a przynajmniej myślę, że nazywa się to "biednymi mansami".

tak:

public class MyService : System.Web.Services.WebService 
{ 
    private IMyBusinessService _myService; 

    public MyService(IMyBusinessService myService) 
    { 
     _myService = myService; 
    } 

    public MyService() : this(new MyBusinessServie()) { } 

    [WebMethod] 
    public string HelloWorld() 
    { 
     return _myService.MyMethod(); 
    } 
} 

Ale ja po prostu nie mogę uzyskać moja głowa wokół jak korzystać z kontenera IoC wstrzyknąć moich zależności bo nie mogę dostać się do uruchomienia usługi bez konstruktora bez parametrów. Proszę być uprzejmy, nie jestem doświadczonym programistą i właśnie zacząłem testować wtrysk zależności i sprawiłem, że działa dobrze na mojej aplikacji formularzy okien z mapą struktury, ale utknąłem na tym.

Odpowiedz

33

Niestety, nie ma sposobu, aby wykonać zastrzyk konstruktora za pomocą usług WWW w środowisku ASP.NET. Wymaganiem ASP.NET jest podanie domyślnego konstruktora. Konstruktor MyService znajduje się w pobliżu katalogu głównego kompozycji, który można uzyskać za pomocą tego rodzaju usługi internetowej, bez korzystania z kontenera DI.

W środowisku ASP.NET nie jest niczym niezwykłym posiadanie wielu pierwiastków kompozycji. Które mogą być konstruktorami poszczególnych usług internetowych i stron internetowych. Jeśli używasz ASP.NET MVC, jest to ControllerFactory, który jest bardziej przyjazny dla DI.

Przy waszym wdrożeniu ważna część nie polega na przeniesieniu konstrukcji wykresu obiektów z serwisu internetowego, ponieważ jest to katalog główny składu. Najważniejszą rzeczą do zrobienia jest utrzymanie jak najcieńszej usługi sieciowej, zachowanie większości zależności w zależności od tego, czy można ją przetestować, czy też użyć ponownie. Wyciąganie informacji z nagłówków HTTP jest przykładem zadania, które usługa sieciowa mogłaby następnie przekazać tej informacji do zależności.

Dobra książka do odnoszenia się do wzorów i technik DI jest Dependency Injection in .NET przez Mark Seemann.

Jeśli serwis internetowy realizowany System.Web.IHttpHandler zamiast wynikające z System.Web.Services.WebService można zaimplementować DI tak:

Global.ashx.cs

public class Global : HttpApplication 
{ 
    protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) 
    { 
     var context = ((HttpApplication)sender).Context; 

     var needsMyBusinessService = context.Handler as INeedMyBusinessService; 
     if (needsMyBusinessService != null) 
      needsMyBusinessService.MyBusinessService = new MyBusinessService(); 
    } 
} 

MyService.ashx.cs

public class MyService : IHttpHandler, INeedMyBusinessService 
{ 
    public IMyBusinessService MyBusinessService { get; set; } 

    public bool IsReusable { get { return true; } } 

    public void ProcessRequest(HttpContext context) 
    { 
     // uses my dependency 
    } 
} 

INeedMyBusinessService.cs

public interface INeedMyBusinessService 
{ 
    IMyBusinessService MyBusinessService { get; set; } 
} 

jednak haczyk z tej realizacji jest to, że robi nie pracę z serwisów internetowych, które wdrażają System.Web.Services.WebService jako obiekt usługi internetowej nie jest zainicjowana dopiero po zdarzeniu PreRequestHandlerExecute to wezwanie, które jest ostatnim wydarzeniem przed ProcessRequest nazywa.

Powyższy przykład działa, jeśli chcesz mieć unikalną instancję dla każdej usługi internetowej. Jeśli chcesz mieć to samo wystąpienie (cykl życia Singleton) o wartości MyBusinessService dla każdego żądania usługi internetowej, możesz zaimplementować plik Global.ashx.cs, taki jak:

public class Global : HttpApplication 
{ 
    private static IMyBusinessService businessService; 

    protected void Application_Start(object sender, EventArgs e) 
    { 
     Global.businessService = new MyBusinessService(); 
    } 

    protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) 
    { 
     var context = ((HttpApplication)sender).Context; 

     var needsMyBusinessService = context.Handler as INeedMyBusinessService; 
     if (needsMyBusinessService != null) 
      needsMyBusinessService.MyBusinessService = Global.businessService; 
    } 
} 
Powiązane problemy