【问题标题】:C# MVVM - Model to access ViewModel functionsC# MVVM - 访问 ViewModel 函数的模型
【发布时间】:2014-11-29 10:14:13
【问题描述】:

我正在为 Windows 通用应用程序在 MVVM 中实现 REST API。

一切顺利,但我想解决一件事。

我在模型级别有​​一个 Post 和一个 Comment 类,它们有 Downvote 和 Upvote 功能。 API 调用在 ViewModel 中实现,包括告诉服务器执行 downvote-upvote 的调用。

我想要模型的 Downvote/Upvote 函数来触发 ViewModel 的适当调用。有可能还是我绕错了方向?

【问题讨论】:

    标签: c# mvvm windows-phone win-universal-app


    【解决方案1】:

    你被困在大多数以 MVVM 开始的程序员都被困住的地方。你只看 MVVM 并严格忽略其他一切。

    您看到的是:ModelViewModelView,您尝试将所有业务逻辑放入其中之一。 但是Model 部分不仅仅是带有一点逻辑的 POCO 对象。服务也属于模式。这是您封装所有不属于某个模型的业务逻辑的地方。

    您可以实现一个PostService 类和一个CommentService 类,它们都实现了UpVote/DownVote 功能并从您的ViewModel 调用这些服务。

    public interface ICommentService
    {
        void UpVote(Post post, Comment comment);
        void DownVote(Post post, Comment comment);
    }
    
    public class CommentRestService 
    {
        IRestClient client;
        public CommentRestService(IRestClient client)
        {
            this.client = client;
        }
    
        public void UpVote(Post post, Comment comment)
        {
            var postId = post.Id;
            var commentId = comment.Id;
    
            var request = ...; // create your request and send it
    
            var response = request.GetResponse();
    
            // successfully submitted
            if(response.Status == 200) 
            {
                comment.VoteStatus = VoteType.Up;
                comment.Score += 1;
            }
        }
    
        public void DownVote(Post post, Comment comment)
        {
            var postId = post.Id;
            var commentId = comment.Id;
    
            var request = ...; // create your request and send it
    
            var response = request.GetResponse();
    
            // successfully submitted
            if(response.Status == 200) 
            {
                comment.VoteStatus = VoteType.Down;
                comment.Score -= 1;
            }
        }
    }
    

    在您的 ViewModel 中,您只需通过依赖注入传递服务或通过 ServiceLocator 获取它,然后使用它的方法,而不是在模型上调用 UpVote/DownVote

    // in ViewModel
    
    // get via ServiceLocator or DI
    ICommentService commentService = ...; 
    commentService.UpVote(this.Post, this.SelectedComment);
    

    您也可以在模型上实现此方法,将操作封装到 Comment 类中,即通过将 ScoreVoteStatus 设为“私有集;”

    public class Comment 
    {
        public string Comment { get; set; }
        public Post Post { get; private set; }
        public VoteType VoteStatus { get; private set; }
        public int Score { get; private set; }
    
        public void UpVote(ICommentService commentService) 
        {
            // for this you'd change your Up/Vote method to return only true/false and not 
            // change the state of your model. On more complex operation, return an CommentResult
            // containing all necessary information to update the comment class
            if(commentService.UpVote(this.Post, this)) 
            {
                // only update the model, if the service operation was successful
                this.Score++;
                this.VoteStatus = VoteType.Up;
            }
        }
    }
    

    并通过调用它

    SelectedComment.UpVote(commentService);
    

    首选后一种方法,因为您可以更好地控制Comment 对象,并且Comment 的状态只能通过Comment 及其方法类进行修改。这可以防止在代码中的其他地方意外更改此值并接收不一致的状态(即更改 VoteStatus 而不增加 Score 值)。

    【讨论】:

    • 这似乎是我正在寻找的最接近的解决方案!我实际上以类似方式实现了它,但我没有使用服务和 DI,而是简单地设置了一个位于 VM 和模型之间的单例。
    【解决方案2】:

    Model --> 数据及其相关的赞成/反对票信息。

    视图模型

    --> 赞成/反对票的实施。

    查看

    --> 触发赞成/反对票(例如命令)。

    依赖关系是这样链接的 View -> ViewModel-> Model。这就是模式。

    【讨论】:

    • 我确实意识到了这一点,但我的目标不是调用 ViewModel.DownvoteComment(Comment Comment) 或 (Guid CommentID),而是调用 Comment.Downvote(),然后调用 ViewModel.DownvoteComment( ) 并将其传递给它自己的 Guid。我知道这只是一种化妆,但如果能像这样管理就好了。
    • 但是,正如依赖项向您展示的那样,让模型依赖于您的 ViewModel 是反模式。但你可以做任何事情。是什么阻止您从模型中使用 VM? MVVM 方法有什么问题?
    • MVVM 方法很好,但正如我所说,我希望能够通过模型对象调用方法(调用 Message.Downvote() 看起来比调用 MessageViewModel.Downvote(信息))。虽然我想我想通了。将有一个中间类,充当单例,称为 API,它将包含所有调用,然后 Model 和 ViewModel 级别都可以将这个中间层用于函数,但不会以破坏模式的方式进行通信。
    • 你不应该使用单例,因为你不能替换你的服务以获得更好的测试
    猜你喜欢
    • 1970-01-01
    • 2012-12-23
    • 2018-03-11
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 2016-09-23
    • 2011-08-14
    • 1970-01-01
    相关资源
    最近更新 更多