2011-10-21 16 views
16

Vì vậy, tôi đã gặp khó khăn trong khi cố gắng để có được webservice asmx của tôi để sử dụng tiêm phụ thuộc và sử dụng một IoC để làm điều đó. Tôi muốn dịch vụ web của tôi có thể sử dụng các dịch vụ lớp kinh doanh nội bộ của mình. Webservice sẽ được sử dụng bởi một máy khách bên ngoài từ một miền khác và chủ yếu sẽ được sử dụng để gửi và nhận thông tin về các thực thể như Đơn hàng và Khách hàng.ASMX Dependency Injection và IoC

Một ví dụ sẽ là:

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

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

Tôi muốn sử dụng dependency injection để loại bỏ sự cần thiết của "newing" lên dịch vụ của tôi nhưng tôi không thể tìm ra một cách để làm điều này. Tôi có thể làm cho nó hoạt động bằng cách sử dụng người nghèo DI, hoặc ít nhất tôi nghĩ rằng nó được gọi là "người nghèo".

như thế này:

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

Nhưng tôi chỉ đơn giản là không thể có được quanh đầu tôi làm thế nào để sử dụng một container IoC để tiêm phụ thuộc của tôi, vì tôi không thể nhận được dịch vụ để chạy mà không có một constructor parameterless. Xin hãy tử tế, tôi không phải là một lập trình viên giàu kinh nghiệm và chỉ mới bắt đầu thử nghiệm tiêm phụ thuộc và làm cho nó hoạt động tốt trên các ứng dụng biểu mẫu cửa sổ của tôi với structuremap nhưng bị mắc kẹt trên cái này.

Trả lời

33

Thật không may là không có cách nào để một người thực hiện phép xây dựng với dịch vụ web trong ASP.NET. Đó là một yêu cầu của ASP.NET mà bạn cung cấp một hàm tạo mặc định. Phương thức khởi tạo của MyService gần giống với gốc thành phần mà bạn có thể nhận được với loại dịch vụ web này, mà không sử dụng vùng chứa DI.

Với ASP.NET, nó không phải là bất thường khi có nhiều thành phần gốc. Mà có thể là các nhà xây dựng của các dịch vụ web cá nhân và các trang web. Nếu bạn đang sử dụng ASP.NET MVC nó là ControllerFactory, đó là DI thân thiện hơn.

Với việc triển khai của bạn, phần quan trọng không phải là di chuyển việc xây dựng biểu đồ đối tượng từ dịch vụ web vì đây là gốc thành phần của bạn. Điều chính cần làm là giữ cho dịch vụ web mỏng nhất có thể, giữ hầu hết logic trong sự phụ thuộc để nó có thể được kiểm tra hoặc tái sử dụng. Việc lấy thông tin ra khỏi các tiêu đề HTTP là một ví dụ về một nhiệm vụ mà dịch vụ web có thể sau đó truyền thông tin đó đến phụ thuộc.

Một cuốn sách hay để tham khảo các mẫu và kỹ thuật DI là Dependency Injection in .NET bởi Mark Seemann.

Nếu dịch vụ web của bạn thực hiện System.Web.IHttpHandler thay vì bắt nguồn từ System.Web.Services.WebService bạn có thể thực hiện DI bạn như vậy:

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

Tuy nhiên, nắm bắt việc triển khai này là đó là không không làm việc với các dịch vụ web mà thực hiện System.Web.Services.WebService như các đối tượng dịch vụ web không được khởi tạo cho đến sau sự kiện PreRequestHandlerExecute là cuộc gọi, đó là sự kiện cuối cùng trước khi ProcessRequest được gọi.

Ví dụ trên hoạt động nếu bạn muốn có một phiên bản duy nhất cho từng dịch vụ web. Nếu bạn muốn có cùng một ví dụ (vòng đời Singleton) là MyBusinessService cho mỗi yêu cầu dịch vụ web, bạn có thể triển khai tệp Global.ashx.cs như sau:

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