【问题标题】:Service Client Interface for Simple Dependency Injection?用于简单依赖注入的服务客户端接口?
【发布时间】:2024-04-26 13:30:01
【问题描述】:

我目前正在我的 ViewModel 中新建一个 WCF ServiceClient 实例并直接调用服务公开的方法,例如:

private string LoadArticle(string userName)
{
   MyServiceClient msc = new MyServiceClient();
   return msc.GetArticle(userName);
}

这导致 ViewModel 和 Service 紧密耦合。我想使用构造函数依赖注入,传入 IMyServiceClient 接口,从而允许我对 ViewModel 进行单元测试。

我打算在我的 ViewModel 中实现接口:

public class ArticleViewModel : IServiceClient
{
    private IServiceClient ServiceClient { get; set; }

    public ArticleViewModel(IserviceClient serviceClient)
    {
       this.ServiceClient = serviceClient;
    }

我了解这将如何工作,但我正在努力实际编写界面:

Interface IMyServiceClient
{
   // ?
}

找不到这样的例子,可能是谷歌搜索不正确。

好的,这就是我解决这个问题的方法:

客户端中的服务引用提供了一个名为 IServiceChannel 的接口,它为您的服务定义了一个通道。我在运行时命中的第一个 ViewModel 中创建了通道工厂。然后,此实例通过整个应用程序中后续 ViewModel 的构造函数传递。我只是将它传递给我的 ViewModel 构造函数,如下所示:

 public ArticleDataGridViewModel(IMyServiceChannel myService)
    {
        this.MyService = myService;

        var factory = new ChannelFactory<IMyServiceChannel>("BasicHttpBinding_IMyService");
        MyService = factory.CreateChannel(); 

绑定细节可以在app.config中找到。

【问题讨论】:

  • 只是公开您在服务上的方法?即文章GetArticle(字符串用户名)?
  • 我不明白?我的方法在我的服务中实现,我不想在我的客户端应用 ViewModel 中实现它们,我只想调用它们?
  • 你不会再次实现它们,你只会通过你的 VIewModel “代理”它们。也就是说,您将公开最终调用内部服务客户端实例的类似方法。
  • 你不会再次实现它们,你只会通过你的 VIewModel “代理”它们。也就是说,您将公开最终调用内部服务客户端实例的类似方法。不过,我认为将服务客户端保留在视图模型中并不是一个好主意,将它放在控制器上可能会更好。
  • 是的。我认为令人困惑的是你真的想注入你的服务而不是 wcf 服务客户端。所以有两个服务都实现了 aame 接口。一个直接进入数据库(并通过 WCF 公开,一个包装 wcf 服务客户端并与第一个服务对话以获得结果

标签: c# wpf wcf mvvm dependency-injection


【解决方案1】:

您的 ViewModel 不是服务,因此它也不应该实现 IServiceClient

ViewModels 准备要在 View 中显示的数据并实现表示逻辑(触发 Action A 时会发生什么?更新字段 A,更改字段 B 的值等。当 A 为空时是否启用文本字段 C?)。

话虽如此,您所要做的就是将您的服务传递到您的 ViewModel 并调用它的方法。

public class ArticleViewModel : ViewModelBase 
{
    private IServiceClient serviceClient;
    public ArticleViewModel(IServiceClient client) 
    {
        this.serviceClient = client;
    }

    private string LoadArticle(string userName) 
    {
        return this.serviceClient.GetArticle(userName);
    }
}

您的 ViewModel 不需要实现该接口。只需将其传递给构造函数并将其保存到私有字段中即可。

【讨论】:

    最近更新 更多