Dependencies ASMX依赖注入和IoC

Dependencies ASMX依赖注入和IoC,dependencies,inversion-of-control,asmx,code-injection,Dependencies,Inversion Of Control,Asmx,Code Injection,因此,当我试图让我的asmx Web服务使用依赖注入并使用IoC来实现时,我陷入了困境。我希望我的Web服务能够使用我的内部业务层服务。webservice将由来自不同域的外部客户端使用,主要用于发送和接收有关实体(如订单和客户)的信息 例如: 公共类MyService:System.Web.Services.WebService { [网络方法] 公共字符串HelloWorld() { 返回新的MyBusinessService().MyMethod(); } } 公共类MyBusiness

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

例如:

公共类MyService:System.Web.Services.WebService
{
[网络方法]
公共字符串HelloWorld()
{
返回新的MyBusinessService().MyMethod();
} 
}
公共类MyBusinessService:IMyBusinessService
{
公共字符串MyMethod()
{
回复“你好”;
}
}
我想使用依赖注入来消除“更新”我的服务的需要,但我想不出一个方法来做到这一点。我可以用穷人的DI让它工作,或者至少我认为它被称为“穷人”

像这样:

公共类MyService:System.Web.Services.WebService
{
私有IMyBusinessService_myService;
公共MyService(IMyBusinessService MyService)
{
_myService=myService;
}
public MyService():此(新的MyBusinessService()){}
[网络方法]
公共字符串HelloWorld()
{
返回_myService.MyMethod();
}
}
但是,我无法理解如何使用IoC容器来注入依赖项,因为如果没有无参数构造函数,我无法运行服务。
请原谅,我不是一个经验丰富的程序员,我刚刚开始测试依赖注入,并使它在我的windows窗体应用程序structuremap上正常工作,但在这个应用程序上遇到了问题。

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

在ASP.NET中,具有多个合成根并不罕见。可以是单个web服务和web页面的构造函数。如果您使用的是ASP.NET MVC,那么它就是ControllerFactory,它对DI更加友好

在您的实现中,重要的部分不是将对象图的构造从web服务移开,因为这是您的合成根。要做的主要事情是使web服务尽可能精简,将大部分逻辑保留在依赖项中,以便对其进行测试或重用。从HTTP头中提取信息是一个示例,web服务可以将该信息传递给依赖项

Mark Seemann是一本关于DI模式和技术的好书

如果您的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;
    }
}

Web服务上只能有一个无参数构造函数。但是,您可以做的是在WebService类上有一个属性,并且在无参数构造函数中调用类似于_myDependency=container.resolve()的东西