2011-10-21 169 views
16

因此,我试图让我的asmx webservice使用依赖注入并使用IoC来实现它。我希望我的web服务能够使用我的内部业务层服务。 Web服务将由来自不同域的外部客户端使用,主要用于发送和接收有关实体(如订单和客户)的信息。ASMX依赖注入和IoC

一个例子是:

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

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

我想使用依赖注入,以消除“newing”我的服务的需要,但我不能想出一个办法做到这一点。我可以使用可怜的人DI进行工作,或者至少我认为它被称为“可怜的人”。

这样的:

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

但我只是不能让我围绕着如何使用IoC容器注入我的依赖,因为我不能去无参数的构造函数运行服务头。 请友好,我不是一个有经验的程序员,并且刚开始测试依赖注入,并使它在结构映射的Windows窗体应用程序上正常工作,但陷入了这个问题。

回答

33

不幸的是,在ASP.NET中没有任何方法可以使用web服务执行构造函数注入。您提供一个默认构造函数是ASP.NET的一个要求。 MyService的构造函数与使用这种类型的Web服务可以获得的组合根无关,但不使用DI容器。

使用ASP.NET,拥有多个组合根并不少见。它可以是各个Web服务和Web页面的构造函数。如果您使用的是ASP.NET MVC,则它是ControllerFactory,它对DI更友好。

随着您的实现,重要的部分是不要从Web服务中移动对象图的构造,因为这是您的组合根。要做的主要事情是保持Web服务尽可能的简洁,将大部分逻辑放在依赖项中,以便测试或重用。从HTTP头中提取信息是Web服务可以将该信息传递给依赖项的任务示例。

一本关于DI模式和技术的好书是Mark Seemann的Dependency Injection in .NET

如果你的Web服务实现System.Web.IHttpHandler,而不是从System.Web.Services.WebService派生,你可以实现你的DI像这样:

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

但是这个实现的前提条件是,是不会有实现System.Web.Services.WebService作为Web服务对象未初始化之后才PreRequestHandlerExecute事件调用,这是最后一个事件ProcessRequest调用之前Web服务工作。

上述示例适用于您希望每个Web服务都有唯一实例的情况。如果您希望为每个Web服务请求拥有相同的实例(单例生命周期)MyBusinessService,则可以像这样实现Global.ashx.cs文件:

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