调用Silverlight Ria服务设计问题

调用Silverlight Ria服务设计问题,silverlight,interface,ria,Silverlight,Interface,Ria,我正在尝试创建一个调用Ria WebServices的silverlight应用程序,问题是我不想将Ria服务(紧密耦合)连接到我的ViewModel中 我的想法是创建一个接口包装器。例如,如果我想使用Ria认证服务,我只需要创建自己的服务 public interface IMyAuthenticationService { void Login(); void LoginCallBack(LoginResult result); event MyHandler Login

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

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

public interface IMyAuthenticationService
 {
   void Login();
   void LoginCallBack(LoginResult result);
   event MyHandler LoginComplete()
 }
然后,我可以在viewmodel中为任何身份验证服务使用上述接口的实现。这有望减少与Ria服务的耦合,因为上面的接口是通用的


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

我建议您构建一个紧密耦合的模型层,以便与您的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);
        }
    }
}
如果需要,服务代理和接口可以编译成单独的类库,然后由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>
因此,在上面的示例中,我们看到Web服务和silverlight应用程序的模型是紧密耦合和集成的。带有ServiceAgent和iSeries接口的模型可以构建在自己的Silverlight类库中,并与企业解决方案中的各种Silverlight应用程序共享。由于RIA确实要求提供者和消费者紧密耦合,限制这种依赖性将防止将来出现问题,正如您在问题中指出的那样


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

我不确定我是否完全理解了你的意思。你是在建议客户端的逻辑流程是:ViewModel->TighlyCoupledModelLayer->RIA Context Proxy。如果您不介意发布一个非常简单的示例,我将非常感激。明天我将制作一个示例,很抱歉,我没有尽快回复您。该示例将包含从服务后端(通过代理)到视图模型(通过绑定UI)的所有层的一些代码。唯一紧密耦合的部分是RIA服务代理的“模型”。
<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>
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();
        }
    }
}