ASMX依赖注入和IoC

问题描述 投票:16回答:2

所以我在尝试让我的asmx webservice使用依赖注入和使用IoC来实现时遇到了困难。我希望我的webservice能够使用我的内部业务层服务。 Web服务将由来自不同域的外部客户端使用,主要用于发送和接收有关订单和客户等实体的信息。

一个例子是:

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窗体应用程序上正常工作,但却陷入了困境。

dependencies inversion-of-control asmx code-injection
2个回答
35
投票

遗憾的是,没有任何方法可以在ASP.NET中使用Web服务执行构造函数注入。 ASP.NET提供了一个默认构造函数。 MyService的构造函数与使用此类Web服务可以获得的组合根一样接近,而不使用DI容器。

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

对于您的实现,重要的部分不是从Web服务移动对象图的构造,因为这是您的组合根。要做的主要是保持Web服务尽可能薄,将大多数逻辑保留在依赖项中,以便可以对其进行测试或重用。从HTTP标头中提取信息是Web服务可以将该信息传递给依赖关系的任务的示例。

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

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

Globalaasaksasisa

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事件之后才初始化Web服务对象,这是调用ProcessRequest之前的最后一个事件。

如果您希望为每个Web服务提供唯一的实例,则上述示例有效。如果你想为每个web服务请求拥有相同的MyBusinessService实例(Singleton生命周期),你可以像这样实现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;
    }
}

1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.