ASMX 依赖注入和 IoC

Posted

技术标签:

【中文标题】ASMX 依赖注入和 IoC【英文标题】:ASMX Dependency Injection and IoC 【发布时间】:2011-12-12 08:19:02 【问题描述】:

所以我在尝试让我的 asmx webservice 使用依赖注入并使用 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";
    

我想使用依赖注入来消除“更新”我的服务的需要,但我想不出一种方法来做到这一点。我可以使用穷人 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 窗体应用程序上正常工作,但卡在了这个上。

【问题讨论】:

【参考方案1】:

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

对于 ASP.NET,有多个组合根并不罕见。它可以是各个 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 服务一起工作,因为 Web 服务对象在调用 PreRequestHandlerExecute 事件之后才被初始化,即调用ProcessRequest 之前的最后一个事件。

如果您希望每个 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;
    

【讨论】:

【参考方案2】:

您只能在 WebService 上使用无参数构造函数。但是,您可以做的是在 WebService 类上拥有一个属性,并在无参数构造函数内部调用类似 _myDependency = container.resolve();

【讨论】:

以上是关于ASMX 依赖注入和 IoC的主要内容,如果未能解决你的问题,请参考以下文章

控制反转(IOC)和依赖注入(DI)的区别

控制反转(IOC)和依赖注入(DI)的区别

什么是依赖注入 IoC

PHP 依赖注入(DI) 和 控制反转(IoC)

IOC 控制反转IOC 简介 ( 依赖注入的两种实现方式 | 编译期注入 | 运行期注入 )

学习spring容器IOC之依赖和依赖注入