【问题标题】:ASP.NET MVC Dependency Injection Unity with WCF services - working sample solution带有 WCF 服务的 ASP.NET MVC 依赖注入 Unity - 工作示例解决方案
【发布时间】:2023-03-18 19:49:01
【问题描述】:

我正在寻找一个使用 Unity 并调用 WCF 服务的 ASP.NET MVC Web 应用程序的工作示例。我已经看过很多关于如何向 WCF 服务添加依赖注入的解释,但坦率地说,我有点过头了。我也是 WCF 服务的新手,这也无济于事。

我目前正在为我们的 ASP.NET MVC 应用程序使用 Unity 和构造器注入,但到目前为止我们还没有使用任何 WCF Web 服务。计划是开始使用 Web 服务,但我对如何将 Unity 与它们结合起来感到非常困惑。

我想要一个很好的工作示例,我可以通过它来更好地了解如何去做。

【问题讨论】:

  • FWIW,我的书有很多与之相关的示例代码。它没有调用 WCF 服务的 ASP.NET MVC 应用程序,但它确实在 ASP.NET MVC 和使用 DI 使用 WCF 服务的 WPF 应用程序中都有 DI 的示例。 affiliate.manning.com/idevaffiliate.php?id=1150_236

标签: asp.net-mvc wcf dependency-injection unity-container


【解决方案1】:

我会尽力为您提供一些指导。

假设您有一个像这样定义的现有产品 WCF 服务(我们不关心实现,目前这并不重要,您可以根据需要实现它,与硬编码值不同,通过一个 SQL 数据库和一个 ORM,以使用云上的另一个服务):

[DataContract]
public class Product
{
    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string Name { get; set; }
}

[ServiceContract]
public interface IProductsService
{
    [OperationContract]
    Product Get(int id);
}

现在,在您的 ASP.NET MVC 应用程序中,第一步是通过指向 WSDL 添加服务引用。这将生成代理客户端类。

接下来您可以将Unity.Mvc3 NuGet 包添加到您的 MVC 应用程序中

然后在您的Application_Start 中,您可以配置容器(显然可以将此配置外部化为单独的方法,以避免将您的 Global.asax 与它混淆):

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    var container = new UnityContainer();
    container
        .RegisterType<IProductsService, ProductsServiceClient>()
        .Configure<InjectedMembers>()
        .ConfigureInjectionFor<ProductsServiceClient>(new InjectionConstructor("*"));
    DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}

此配置中使用的IProductsServiceProducsServiceClient 是您导入Web 服务定义时生成的代理类。

从现在开始,事情变得微不足道:

public class HomeController : Controller
{
    private readonly IProductsService _productsService;
    public HomeController(IProductsService productsService)
    {
        _productsService = productsService;
    }

    public ActionResult Index()
    {
        var product = _productsService.Get(1);
        return View(product);
    }
}

还有一些对应的Index视图:

@model Product
<div>
    @Html.DisplayFor(x => x.Name)
</div>

正如您从这个示例中看到的,感谢IProductsService 抽象,HomeController 与服务的任何具体实现完全解耦。在今天的 Global.asax 中,您决定使用 WCF (ProductsServiceClient),但明天您可能会决定使用一些完全不同的实现。只需对 DI 容器配置进行一次更改,您就可以切换实现。由于这种弱耦合,您的控制器完全可以独立进行单元测试。

这里要意识到的重要一点是,您的业务是 Product 类和 IProductsService 接口。这反映了您的域。这是 MVC 中的 M。实现可能会发生变化,但这应该保持不变,否则您错误地确定了您的业务需求,从长远来看这可能是灾难性的。

备注:在这个例子中我没有涉及的一件事是视图模型的使用,这是非常重要的。在正确架构的 ASP.NET MVC 应用程序中,您永远不应该将域模型传递给您的视图(在本例中为 Product 类)。您应该使用视图模型。视图模型是专门为满足给定视图的要求而设计的类。因此,在现实世界的 ASP.NET MVC 应用程序中,您将拥有一个 ProductViewModel 类,Product 域模型将在控制器操作中映射到该类,并且此 ProductViewModel 将被传递给视图。这些视图模型应该在 MVC 项目中定义,因为与您的域模型相反,它们不可重用并且仅反映单个视图的特定要求。为了简化域模型和视图模型之间的映射,您可以查看AutoMapper

【讨论】:

  • 优秀的文章,很好的解释。这解决了我关于 DI 的很多问题。但是,我仍然认为,与其在 MVC 项目中添加服务引用,不如定义您的 web.config 中的端点,并且可以在 Global.asax 中创建一个正在运行的实例。您知道我们如何实现这一点吗?或者您认为这不是正确的方法?
  • 如果您不想在 VS 中使用添加服务引用向导,您可以直接使用 VS SDK 中的 svcutil.exe 工具从现有的 WCF 服务生成强类型代理。至于您关于在 web.config 中配置端点和在 Global.asax 中创建运行实例的问题,我不太明白您的意思。
  • 使用这种方式,需要在web项目中添加服务引用吗?
【解决方案2】:

听起来您已经在使用 Unity 注入 MVC 控制器,而您要做的就是开始注入您托管的 WCF 服务。要注入 WCF 服务,您需要使用 IInstanceProvider

完整的工作解决方案在这里:

http://orand.blogspot.com/2006/10/wcf-service-dependency-injection.html

你需要 4 个非常简单的类:

MyServiceHostFactory 
MyServiceHost 
DependencyInjectionServiceBehavior
DependencyInjectionInstanceProvider 

定义这些,指定您的新 ServiceHostFactory:

<%@ ServiceHost
Service="NamespaceC.ServiceLayer, AssemblyC"
Factory="NamespaceD.MyServiceHostFactory, AssemblyD"
%>

你就完成了。

【讨论】:

  • 你知道一个使用 Unity 和 Spring.NET 的例子吗?最好有一个可下载的 zip 文件。
【解决方案3】:

我知道这有点晚了,但我编写了一个 Nuget 包来简化在 MVC/WebApi 应用中使用 WCF 的过程,它利用了 Unity。

查看 CodeplexGitHub 上的 Unity.Mvc.Wcf 了解详细信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    相关资源
    最近更新 更多