Domæne klasser i Silverlight

30 Jul

Jeg har fik et spørgsmål fra Morten Schmidt omkring deling af domæne klasser mellem serveren og Silverlight klienten. Jeg tror at det er et spørgsmål som mange Silverlight udviklere sidder med, så lad os kigge lidt nærmere på hvordan det kan gøres.

 

Simpelt kodeeksempel

Først skal vi have oprettet en solution og lidt projekter; jeg har startet med at lave en Silverlight applikation og en webapplikation til at hoste den. Silverlight klienten kalder jeg (meget opfindsomt) MyClientApplication og webapplikationen kalder jeg MyHostWebApplication. Dernæst tilføjer jeg et almindeligt klassebibliotek til solutionen kaldet ServerModel samt et Silverlight klassebibliotek kaldet ClientModel.

 

2009-07-30_234505

 

Nu skal vores domæne klasser tilføjes til løsningen. I ServerModel tilføjer jeg klassen Customer og tilføjer de nødvendige properties.

 

  1: using System;
  2: using System.Collections.Generic;
  3: using System.Linq;
  4: using System.Text;
  5: using System.Runtime.Serialization;
  6: 
  7: namespace ServerModel
  8: {
  9:   [DataContractAttribute(Name = "Customer")]
 10:   public class Customer
 11:   {
 12:     [DataMember]
 13:     public Guid Id { get; set; }
 14:     [DataMember]
 15:     public string FirstName { get; set; }
 16:     [DataMember]
 17:     public string LastName { get; set; }
 18:     [DataMember]
 19:     public string FullName { get { return FirstName + " " + LastName; } set { } }
 20: 
 21: #if !SILVERLIGHT
 22:     [DataMember]
 23:     public string Address { get; set; }
 24: #endif
 25:   }
 26: }
 27: 

 

Bemærk at jeg har kun ønsker propertien Address med såfremt vi ikke er i et Silverlight projekt.

Nu kommer det store trick! Det vi egentlig ønsker, er jo at have den samme klasse i vores ClientModel projekt – så det er bare det vi gør. Jeg højreklikker på projektet og vælger Add –> Existing Item og finder Customer.cs filen. I stedet for at vælge Add vælger jeg Add As Link.

 

2009-07-30_235918

 

Det betyder egentlig, at i stedet for at tilføje filen, bliver der tilføjet et link til filen. Det betyder også, at bliver der lavet en opdatering i det ene projekt, slår det automatisk igennem på det andet projekt.

Når vi bruger klassen i vores ServerModel, bliver properties Address inkluderet, men når vi bruger den i vores ClientModel, bliver den udeladt – ganske fikst!

Lad mig prøve at bruge vores klasse; jeg opretter en service i vores webapplikation, der returner en udfyldt instans af vores Customer klasse. I clientapplikationen tilføjer jeg en reference til vores ClientModel projekt og laver en ServiceReference til vores service i webapplikationen.

I codebehind på vores XAML fil tilføjer jeg et kald til vores service metode, hvor jeg henter den instantierede kunde og sætter DataContext på siden.

 

CS-filen:

  1: using System;
  2: using System.Collections.Generic;
  3: using System.Linq;
  4: using System.Net;
  5: using System.Windows;
  6: using System.Windows.Controls;
  7: using System.Windows.Documents;
  8: using System.Windows.Input;
  9: using System.Windows.Media;
 10: using System.Windows.Media.Animation;
 11: using System.Windows.Shapes;
 12: using ServerModel;
 13: using MyClientApplication.ServiceReference1;
 14: 
 15: namespace MyClientApplication
 16: {
 17:   public partial class MainPage : UserControl
 18:   {
 19:     public MainPage()
 20:     {
 21:       InitializeComponent();
 22: 
 23:       MyServiceClient client = new MyServiceClient();
 24:       client.RetrieveCustomerCompleted += (se, ea) =>
 25:         {
 26:           ServerModel.Customer c = ea.Result;
 27:           //c.Address <-- here you can see that the address property is not available
 28:           LayoutRoot.DataContext = c;
 29:         };
 30:       client.RetrieveCustomerAsync();
 31:     }
 32:   }
 33: }
 34: 

 

XAML filen:

  1:   <StackPanel
  2:     x:Name="LayoutRoot">
  3:     <TextBlock
  4:       Text="{Binding Id}" />
  5:     <TextBlock
  6:       Text="{Binding FullName}" />
  7:     <TextBlock
  8:       Text="{Binding Address}" />
  9:   </StackPanel>
 10: 

 

Kører jeg webapplikationen nu, vil jeg få vist Id og FullName. Jeg vil ikke få vist Address, da den ikke er en del af den kompilerede klasse til Silverlight.

Den fulde kildekode til eksemplet finder du på mit skydrive.

Det er en meget forenklet udgave af, hvordan vi normalt opbygger den grundlæggende arkitektur i vores Silverlight projekter. Oftes vil vores services også være adskilt i seperate projekter og der vil være repositories der håndterer adgangen til vores services fra henholds klient og server.

I mange tilfælde vil det kunne betale sig, at tage mere eller mindre, udgangspunkt i et eksisterende framework. Der findes flere frameworks, der gør meget af det grundlæggende arkitektarbejde for os – herunder .NET RIA Services.

 

.NET RIA Services

Nikhil har skrevet en meget sjov post, der kort fortæller om, hvad .NET RIA Services er, og hvorfor man som udvikler bør anvende det (eller et lignende framework).

http://www.nikhilk.net/NET-RIA-Services-Twitter-Pitch.aspx

 

Gruppe på LinkedIn

For netop at få diskuteret nogle af de problemstillinger, der kan være i forbindelse med Silverlight udviklinger, er der en gruppe på LinkedIn til netop det. Formålet med gruppen er at mødes 5-6 gange årligt, diskutere problemstillinger og ellers få udvekslet lidt erfaringer.

http://www.linkedin.com/groups?about=&gid=2085262&trk=anet_ug_grppro

 

Happy Coding!

Thomas Castøe Martinsen

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

%d bloggers like this: