Я бы посоветовал вам создать тесно связанный слой Models для использования с вашими службами RIA.Если слой Model способен выполнять всю работу, требуемую с помощью RIA, (он должен быть независимо тестируемым), тогда вы можете начать переводить эти операции через вашу View Model, используя интерфейс, как вы предлагали;Вы можете создать слой Models в отдельной библиотеке 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);
}
}
}
Также имеется интерфейс 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);
}
}
Агент службы и интерфейс могут быть скомпилированы вОтдельная библиотека классов, если вы хотите, затем используется View Model и View вашего приложения 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;
});
}
}
}
И, наконец, View:
<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();
}
}
}
Итак, мы видим, что вВ приведенных выше примерах веб-служба и модель приложения silverlight тесно связаны и интегрированы.Модель с интерфейсами ServiceAgent и IService может быть встроена в собственную библиотеку классов Silverlight и использоваться совместно с различными приложениями Silverlight в вашем корпоративном решении.Поскольку RIA действительно требует, чтобы поставщик и потребитель были так тесно связаны, ограничение этой зависимости предотвратит проблемы в будущем, как вы указали в вопросе.
Теперь, когда поставщик и потребитель готовы, основноеПриложение Silverlight подключает модель через модель представления к представлению.(ViewModels и Views, как правило, также тесно связаны).