如何在ASP.NET web服务中使用依赖注入和仓储模式?

7

在普通的ASP.NET MVC页面中,存储库被传递到控件的构造函数中。然后测试可以实例化控制器并传入模拟存储库。

那么我该如何在Web服务中实现这一点呢?我看到的问题是我们没有ControllerBuilder.SetControllerFactory的等效物。

有什么最佳实践方法可以让我的IoC框架(Castle)使用正确的存储库实现来实例化我的Web服务?

我认为可能有一种方法是扩展HttpHandler并更改Web服务实际实例化的方式。我相信这就是MVC框架的实现方式。


你使用哪种技术来实现你的Web服务?ASP.NET Web Services还是Windows Communication Foundation? - Mark Seemann
ASP.NET Web Services。然而,在阅读jrista的答案后,我认为如果我真的想要注入依赖项,那么研究WCF可能是值得的。我考虑只使用两个构造函数 - 一个带有存储库作为参数(测试将调用此函数),另一个默认构造函数将硬编码:this(new IRepository),并由ASP.NET框架调用。 - Brandon O'Rourke
6个回答

2
这是一个好问题,我也遇到了同样的问题。我认为如果你使用.asmx文件创建Web服务,则不可能使用构造函数注入。如果你使用WCF来实现Web服务,则可以使用构造函数注入。
在我的.asmx Web服务中,我通过设置属性让DI容器设置依赖项。由于我的应用程序也是一个Web表单asp.net应用程序,所以这就是我必须这样做的原因,因为我不能在Web表单上使用构造函数注入。但是我正在使用StructureMap,它有一个BuildUp函数,可以设置已创建对象的属性。虽然不如构造函数注入干净,但是是一个很好的折衷方案。
但是Web服务与Web表单有所不同,因为我可以将构建放在Web表单之外,在Application_PostMapRequestHandler事件中进行。但是我还没有找到在Web服务类创建后触发的事件。因此,在我的Web服务构造函数中,我有以下代码:
ObjectFactory.BuildUp(this);

这是一个反模式。由DI容器初始化的类不应该知道DI容器本身。但我还没有找到更好的解决方案。


1

我相信你正在寻找Castle Windsor WCF Integration Facility。它提供了一个ServiceHost实现,接管您的服务实现的构建过程,利用Windsor IOC。您可以像使用任何其他IoC应用程序一样使用此工具注入依赖项,并且方便的是,它是Castle项目的一部分:

http://www.castleproject.org/container/facilities/trunk/wcf/index.html

如果Castle Project版本不能满足您的需求,我有自己创建的工具可以在发现Castle项目版本之前为Windsor执行相同的操作。它们通常都会执行相同的操作,但是两者处理问题的方式略有不同。

我猜答案是“你不能在ASP.NET Web服务中使用构造函数注入”,因此要么使用BuildUp(this),要么使用带有Castle的WCF。 - Brandon O'Rourke
1
实际上,您应该能够将Castle Windsor与ASMX风格的服务一起使用(如果这是您的意思)。我以为您在问WCF,但我不明白为什么您不能将Windsor集成到ASMX管道中。虽然可能没有WCF那么容易,但这应该不是不可能的。 - jrista
@jrista,由于在asmx文件中不允许使用ServiceHost,你有没有关于如何为asmx服务实现DI的示例? - Varun

0

你有没有什么理由不能创建一个带有所需构造函数的自定义类,然后在asmx中实例化该类的对象,然后将所有操作委托给该对象?

我通常会像这样创建这些类型的对象:

var o = CustomClass.Create();

public class CustomClass
{
  public static CustomClass Create()
  {
    return IoC.Resolve<CustomClass>();
  }
}

public static class IoC
{
  public T Resolve<T>()
  {
    return yourStaticReferenceToPreferredContainer.Resolve<T>();
  }
}

0

定义一个基类并在其中使用属性注入。Pete已经说过了,但你要做的是:ObjectFactory.BuildUp(this);

不同之处在于,我会将其放在Web服务的基类中,这样对于特定的实现就是“自动的”。

这样只需要一行代码,所以除非你有在运行时切换DI容器的明确需求(不太可能),否则不需要关心它。如果你仍然需要这个功能,只需将调用移动到一个单独的类中,并在那里使用特定的DI容器即可。


0


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接