【问题标题】:Calling Silverlight Ria Services Design Issue调用 Silverlight Ria 服务设计问题
【发布时间】:2011-11-04 18:39:50
【问题描述】:

我正在尝试创建一个调用 Ria WebServices 的 silverlight 应用程序,问题是我不希望将 Ria 服务(紧密耦合)连接到我的 ViewModel 中。

我的想法是创建一个接口包装器。例如,如果我想使用 Ria 身份验证服务,我只需创建自己的

public interface IMyAuthenticationService
 {
   void Login();
   void LoginCallBack(LoginResult result);
   event MyHandler LoginComplete()
 }

然后我可以在我的视图模型中为任何身份验证服务使用上述接口的实现。这有望减少与 Ria 服务的耦合,因为上述接口是通用的。

我想知道您是否可以就上述想法向我提供任何反馈。我不确定这是否是处理这种情况的好方法。

【问题讨论】:

    标签: silverlight interface ria


    【解决方案1】:

    我建议您构建一个紧密耦合的模型层以用于您的 RIA 服务。如果模型层能够通过 RIA 完成所需的所有工作,(它应该是可独立测试的)然后您可以使用您建议的接口通过您的视图模型开始转换这些操作;您可以在单独的 Silverlight 库中构建模型层。

    我通过使用 TDD 的企业解决方案成功地做到了这一点。如果需要,我可以提供更具体的代码示例,但即使是简单的服务调用也会有很多类。我可以添加一些代码示例。

    例如,从底部(服务)到顶部(视图):

    我们从非常复杂的 MultiplyService 开始:

    namespace StackOverflow.Tutorial.Web
    {
        using System;
        using System.ComponentModel;
        using System.ComponentModel.DataAnnotations;
        using System.ServiceModel.DomainServices.Hosting;
        using System.ServiceModel.DomainServices.Server;
    
        [EnableClientAccess()]
        public class MultiplyService : DomainService
        {
            [Invoke]
            public MultiplyDTO Multiply(MultiplyDTO input)
            {
                input.Answer = input.A * input.B;
                return input;
            }
    
            public class MultiplyDTO
            {
                public int Answer { get; set; }
                public int A { get; set; }
                public int B { get; set; }
            }
        }
    }
    

    这通过MultiplyContext 类向我们的 Silverlight 客户端公开了一些 RIA 魔法。我们在模型的 Silverlight 端使用这个类:

    using System;
    using StackOverflow.Tutorial.Web;
    using System.ServiceModel.DomainServices.Client;
    
    namespace StackOverflow.Tutorial.Models
    {
        // This class is tightly coupled to 
        public class MultiplyServiceAgent : IMultiplyServiceAgent
        {
            public void Multiply(int a, int b, Action<int> callback)
            {
                MultiplyContext context = new MultiplyContext();
                MultiplyDTO question = new MultiplyDTO() { A = a, B = b };
    
                context.Multiply(question, (answer) =>
                {
                    callback(answer.Value.Answer);
                }, null);
            }
        }
    }
    

    我还包括一个接口IMultiplyServiceAgent

    using System;
    using System.ServiceModel.DomainServices.Client;
    using StackOverflow.Tutorial.Web;
    
    namespace StackOverflow.Tutorial.Models
    {
        public interface IMultiplyServiceAgent
        {
            void Multiply(int a, int b, Action<int> callback);
        }
    }
    

    如果您愿意,可以将服务代理和接口编译到单独的类库中,然后供silverlight 应用程序的视图模型和视图使用,如下所示。首先是 ViewModel:

    using System;
    using System.Net;
    using System.Windows;
    using StackOverflow.Tutorial.Models;
    
    namespace StackOverflow.Tutorial.ViewModels
    {
        public class MultiplyViewModel : DependencyObject
        {
            IMultiplyServiceAgent agent = new MultiplyServiceAgent();
    
            public int A
            {
                get { return (int)GetValue(AProperty); }
                set { SetValue(AProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for A.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty AProperty =
                DependencyProperty.Register("A", typeof(int), typeof(MultiplyViewModel), new PropertyMetadata(0));
    
            public int B
            {
                get { return (int)GetValue(BProperty); }
                set { SetValue(BProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for B.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty BProperty =
                DependencyProperty.Register("B", typeof(int), typeof(MultiplyViewModel), new PropertyMetadata(0));
    
            public int Answer
            {
                get { return (int)GetValue(AnswerProperty); }
                set { SetValue(AnswerProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for Answer.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty AnswerProperty =
                DependencyProperty.Register("Answer", typeof(int), typeof(MultiplyViewModel), new PropertyMetadata(0));
    
            public void Calculate()
            {
                agent.Multiply(this.A, this.B, (answer) =>
                    {
                        this.Answer = answer;
                    });
            }
        }
    }
    

    最后是视图:

    <UserControl x:Class="StackOverflow.Tutorial.Views.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400">
    
        <StackPanel x:Name="LayoutRoot" Background="White">
            <TextBox Name="txtA" Text="{Binding A, Mode=TwoWay}" />
            <TextBox Name="txtB" Text="{Binding B, Mode=TwoWay}" />
            <Button Name="btnCalculate" Content="Calculate" Click="btnCalculate_Click" />
            <TextBlock Name="txtAnswer" Text="{Binding Answer}" />
        </StackPanel>
    </UserControl>
    

    View 后面有一个简单的代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using StackOverflow.Tutorial.ViewModels;
    
    namespace StackOverflow.Tutorial.Views
    {
        public partial class MainPage : UserControl
        {
            public MultiplyViewModel ViewModel { get; set; }
            public MainPage()
            {
                InitializeComponent();
                this.ViewModel = new MultiplyViewModel();
                this.DataContext = this.ViewModel;
            }
    
            private void btnCalculate_Click(object sender, RoutedEventArgs e)
            {
                this.ViewModel.Calculate();
            }
        }
    }
    

    因此,在上面的示例中,我们看到 Silverlight 应用程序的 Web 服务和模型是紧密耦合和集成的。具有 ServiceAgent(s) 和 IService 接口的模型可以构建在其自己的 Silverlight 类库中,并与企业解决方案中的各种 Silverlight 应用程序共享。正如您在问题中指出的那样,由于 RIA 确实要求提供者和消费者如此紧密地耦合,因此限制这种依赖性将防止将来出现问题。

    现在提供者和消费者已准备就绪,Silverlight 主应用程序通过 ViewModel 将模型连接到视图。 (通常,ViewModel 和 View 也是紧密耦合的)。

    【讨论】:

    • 我不确定我是否完全按照您的意思进行操作。您是否建议客户端的逻辑流程为:ViewModel -> TightlyCoupledModelLayer -> RIA 上下文代理。如果您不介意发布一个非常简单的示例,将不胜感激
    • 我明天会做一个样品,抱歉我没有早点回复你。该示例将包含一些代码,用于从服务后端 - 通过代理 - 通过视图模型 - 到绑定 UI 的所有层。唯一紧密耦合的部分是 RIA 服务代理的“模型”。
    猜你喜欢
    • 1970-01-01
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    相关资源
    最近更新 更多