MVVM-Light:在ViewModel中放置WCF调用的位置

时间:2011-07-30 21:18:55

标签: wcf mvvm-light

我正在构建一个WP7应用程序,通过WCF服务获取所有数据。我想在其中实现MVVM-Light,但是在我已经完成的教程中,我看到在ViewModelLocator中它想要在应用程序启动时创建所有ViewModel的静态实例。 我的问题是,在我的VM的构造函数中,我是在哪里进行WCF调用,结果当然会在回调中返回。它在回调中,我将结果分配给我的视图所见的我的可观察集合。这在没有使用MVVM-Light时工作正常但是如果我实现它我在启动时不能有这些WCF调用,因为它们传递参数未知/可用,直到用户使用应用程序(选择项目等) 我尝试将我对WCF的调用移动到我的可观察集合的getter,但它一直在无限循环中调用WCF。 在我见过的所有MVVM-light示例中,我都没有看到任何人调用WCF服务。 有关将WCF调用放在模型中的位置的任何建议吗?

3 个答案:

答案 0 :(得分:2)

与MVVM一样,没有正确的方式......因为它是关于feedom ... :-)

如果需要,您可以将代码放入视图模型中。但是,您还必须在视图模型中生成设计时数据 - 如果要使用它。

这种方法的一大缺点是您在视图模型和服务代码之间引入了耦合(因为您必须在视图模型中实例化服务)。解组件的一般方法是创建一个描述服务的接口,并将实现此接口的对象实例注入到其构造函数的视图模型中。这使您可以创建设计时间和运行时实现,并且您的视图模型不关心它使用哪一个 - 即对象是分离的。

修改

在我的帖子中注入并不暗示您使用注入容器/框架,它只意味着您使用接口来抽象服务行为,然后将实现者或此接口传递给视图模型的构造函数。您现在可以在创建视图模型时传递界面的不同实现,例如在视图定位器中。

建议的模式称为“控制反转”,注入是一种将在别处创建的对象传递到您创建的类中的技术。通过这个,你的班级现在可以免于执行者的任何细节知识,并且它们可以互换。

控制容器的反转 - 比如ninject,unity等 - 只是帮助你自动解析依赖关系,但它们不是必需的用于使用in版本的控制模式。

答案 1 :(得分:1)

我认为在ViewModel中放置WCF调用并不好,您应该将WCF调用封装在另一个类中。您的ViewModel应该只包含GUI逻辑。我认为你从WCF调用获得的是模型,你可以使用模型来创建ViewModel。

答案 2 :(得分:1)

以下是我的CommonServiceHelper.cs文件的示例

   public void GetUserSettings(UserInfoIn input, Action<UserInfoOut, Exception> callback)
    {
        var proxy = new CommonServiceClient();

        try
        {
            proxy.GetUserSettingsCompleted += (sender, eventargs) =>
            {
                var userCallback = eventargs.UserState as Action<UserInfoOut, Exception>;
                if (userCallback == null)
                    return;

                if (eventargs.Error != null)
                {
                    userCallback(null, eventargs.Error);
                    return;
                }
                userCallback(eventargs.Result, null);
            };
            proxy.GetUserSettingsAsync(input, callback);
        }
        catch (Exception ex)
        {
            proxy.Abort();
            //ErrorHelper.WriteErrorLog(ex.ToString());
        }
        finally
        {
            if (proxy.State != CommunicationState.Closed)
            {
                proxy.CloseAsync();
            }
        }
    }

然后在ViewModel中我这样称呼它:

               var serviceCommon = new CommonServiceHelper();
                            serviceCommon.GetUserSettings(userSettingsInput, (result, error) =>
                            {
                                if (result != null && error != null)
                                {
                                    //everything is ok
                                }
                                else
                                {
                                    //handle errors
                                }
                            });