2011-11-04 138 views
0

我正在嘗試創建一個調用Ria WebServices的Silverlight應用程序,問題是我不想將Ria服務連接到我的ViewModel中(緊密耦合)。調用Silverlight Ria服務設計問題

我的想法是創造一個界面包裝。例如,如果我想用利雅身份驗證服務,我會簡單地創建自己的

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

我可以再使用上述接口的實現,在我的視圖模型,對任何身份驗證服務。這將有希望減少對Ria服務的耦合,因爲上述接口是通用的。

我想知道您是否可以向我提供有關上述想法的任何反饋。我不確定這是否是處理這種情況的好方法。

回答

0

我建議你建立一個緊密耦合的模型層,以便與你的RIA服務一起使用。如果模型層能夠完成通過RIA所需的所有工作(它應該是獨立測試的)。然後,您可以使用您所建議的界面,通過View Model來開始翻譯這些操作;您可以在單獨的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; } 
     } 
    } 
} 

其中通過暴露了一些RIA魔術給我們的Silverlight客戶端一個MultiplyContext類。我們在模型消耗在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); 
     } 
    } 
} 

我ASLO包括接口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應用程序的視圖模型和視圖,下面會顯示它們。首先,視圖模型:

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> 

觀背後都有一個簡單的代碼:

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(); 
     } 
    } 
} 

所以我們看到,在上面的例子中,該Web服務和Silverlight應用程序的模型緊密結合並集成在一起。模型 - 帶有ServiceAgent和IService接口可以在自己的Silverlight類庫中構建,並與企業解決方案中的各種Silverlight應用程序共享。既然RIA真的要求提供者和消費者緊密結合,那麼就像你在問題中指出的那樣,限制這種依賴將會防止將來出現問題。

既然供應商和消費者已經準備就緒,主Silverlight應用程序通過ViewModel將Model連接到View。 (ViewModels和Views通常也是緊密耦合的)。

+0

我不知道如果我完全按照你說什麼。你建議客戶端的邏輯流程是:ViewModel - > TightlyCoupledModelLayer - > RIA上下文代理。如果你不介意發佈一個非常簡單的例子,它將不勝感激 – caa

+0

明天我會做一個示例,對不起,我沒有早點回復你。該示例將包含來自服務後端的所有圖層的代碼 - 通過代理 - 通過視圖模型 - 到綁定的用戶界面。唯一可以緊密耦合的部分是RIA服務代理的「模型」。 – EtherDragon