我建議你建立一個緊密耦合的模型層,以便與你的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通常也是緊密耦合的)。
我不知道如果我完全按照你說什麼。你建議客戶端的邏輯流程是:ViewModel - > TightlyCoupledModelLayer - > RIA上下文代理。如果你不介意發佈一個非常簡單的例子,它將不勝感激 – caa
明天我會做一個示例,對不起,我沒有早點回復你。該示例將包含來自服務後端的所有圖層的代碼 - 通過代理 - 通過視圖模型 - 到綁定的用戶界面。唯一可以緊密耦合的部分是RIA服務代理的「模型」。 – EtherDragon