Как разделять код между .Net и Silverlight-проектами. Часть 1
Способ #1. Разделять собственно код (исходники)
Представьте себе, что у нас есть два проекта, к примеру, Silverlight-проект и .Net-проект, которые отчасти дублируют функциональность, по существу, должны использовать одинаковый код (например, при описании отдельных контролов или бизнес-логики).
Естественно, в такой ситуации хочется
- писать код единожды,
- хранить его в одном месте,
- использовать в обоих проектах.
Как это сделать?
Для примера создадим какой-нибудь простой класс с бизнес-логикой.
Конечно, при этом нужно помнить, что Silverlight-версия .Net отличается от полной и, таким образом, выступает как ограничивающий фактор — разделяемый код не может содержать что-то, что не поддерживает Silverlight.
Чтобы сделать разделяемый код более видимым (и заметным, что он именно разделяемый — единообразно для обоих проектов), сделаем отдельную папку (Add → New Solution Folder).
Итак, добавим новый класс Person, в котором будет только несколько полей, касающихся имени человека.
Содержание класса будет следующим:
public class Person
{
private String m_firstName;
private String m_lastName;
public Person()
{
}
private String UpperCaseFirstLetter(String str)
{
if (String.IsNullOrEmpty(str) || str.Length == 0)
return str;
return str[0].ToString().ToUpper() + str.Substring(1, str.Length - 1);
}
public String FirstName
{
get { return m_firstName; }
set { m_firstName = UpperCaseFirstLetter(value); }
}
public String LastName
{
get { return m_lastName; }
set { m_lastName = UpperCaseFirstLetter(value); }
}
public String FullName
{
get { return String.Format("{0} {1}", FirstName, LastName); }
}
}
Следующий шаг: добавить ссылку на этот файл в оба проекта. Для этого для каждого из проектов (Silverlight и WPF) проделываем следующую операцию: Add → Existing Item…, выбираем наш файл и вместо Add выбираем Add as Link:
После этого мы будем иметь ссылку на этот класс в обоих проектах!
Теперь проверим, как этот код будет использоваться в наших проектах.
Добавим немного кода в CodeSharingSL → Page.xaml (для использования WrapPanel нужно добавить в References ссылку на библиотеку Microsoft.Windows.Controls.dll из Silverlight Toolkit):
<UserControl x:Class="CodeSharingSL.Page"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls"
Width="400" Height="300">
<Border x:Name="LayoutRoot" Background="White" Margin="20" HorizontalAlignment="Left" CornerRadius="5" BorderBrush="LightGray" BorderThickness="1" >
<controls:WrapPanel Width="225" Margin="20" >
<TextBlock Width="75" Text="First Name:" />
<TextBox Width="150" Text="{Binding FirstName, Mode=TwoWay}" TabIndex="1" />
<TextBlock Width="75" Text="Last Name:" />
<TextBox Width="150" Text="{Binding LastName, Mode=TwoWay}" TabIndex="2" />
<TextBlock Width="75" Text="Full Name:" />
<TextBox Width="150" x:Name="txtFullName" IsReadOnly="True" InputMethod.IsInputMethodEnabled="False" />
<Button Content="Update full name" Margin="0 10 0 0" Click="Button_Click" />
</controls:WrapPanel>
</Border>
</UserControl>
И изменим соответствующим образом Page.xaml.cs, добавив обработчики событий и привязкук тому самому классу Person:
using SharedCode;
namespace CodeSharingSL
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Page_Loaded);
}
void Page_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = new Person();
}
private void Button_Click(Object sender, RoutedEventArgs e)
{
txtFullName.Text = ((Person)this.DataContext).FullName;
}
}
}
Компилируем, смотрим результат:
Работает!
Поехали дальше. Правим WPF-проект, начнем с xaml-файла CodeSharingWPF →Window1.xaml, в целом все будет аналогично, но не идентично :)
<Window x:Class="CodeSharingWPF.Window1"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid Background="Black">
<WrapPanel Width="225" Margin="20" Background="Black" >
<TextBlock Width="75" Text="First Name:" Foreground="White"/>
<TextBox Width="150" Text="{Binding FirstName}" TabIndex="1" />
<TextBlock Width="75" Text="Last Name:" Foreground="White"/>
<TextBox Width="150" Text="{Binding LastName}" TabIndex="2" />
<TextBlock Width="75" Text="Full Name:" Foreground="White"/>
<TextBox Width="150" x:Name="txtFullName" IsReadOnly="True" InputMethod.IsInputMethodEnabled="False" />
<Button Content="Update Full Name" Margin="0 10" Click="Button_Click" />
</WrapPanel>
</Grid>
</Window>
C#-код будет практически таким же:
using SharedCode;
namespace CodeSharingWPF
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
this.Loaded +=new RoutedEventHandler(Window1_Loaded);
}
void Window1_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = new Person();
}
private void Button_Click(Object sender, RoutedEventArgs e)
{
txtFullName.Text = ((Person)this.DataContext).FullName;
}
}
}
Запускаем, смотрим результат:
Вуаля :) Впереди еще две части: про использование условной компиляции применительно к проблеме разделения кода и про то, как разделять не код, а библиотеки (dll).
Comments
Anonymous
February 08, 2009
Способ #1. Разделять собственно код (исходники)Anonymous
February 08, 2009
В прошлый раз мы разобрались, как разделять код между Silverlight и .NET-проектами на уровне исходниковAnonymous
February 08, 2009
Итак, мы уже умеем делать две вещи: Разделять код между .NET и Silverlight-проектами на уровне исходниковAnonymous
February 08, 2009
В прошлый раз мы разобрались, как разделять код между Silverlight и .NET-проектами на уровне исходников