Dieser Artikel wurde maschinell übersetzt.

div#content td, div#content img{display: block;}

Windows Azure AppFabric-Dienstbus

Erstellen eines kontinuierlichen Clients mithilfe von portablen Klassenbibliotheken

David Kean

Ich fühle mich glücklich, Leben in den Tagen der ständig angeschlossenen Geräte.Ich liebe, dass ich fähig bin zu Antworten auf e-mail mit meinem Handy während der Fahrt im Bus nach Hause.Es ist erstaunlich, in der Lage, Skype mit meiner Familie auf der anderen Seite der Welt und mit Gleichgesinnten Gamern über das Land auf meine Xbox team.In dieser Welt der ständigen Internet-Konnektivität, es ist jedoch, wie Joshua Topolsky es, "ein Missing Link in unsere computing-Erfahrung sagt" (engt.co/9GVeKl).

Diese Missing Link bezieht sich auf den Mangel an was Topolsky ein kontinuierlichen Client aufruft; Das heißt, eine Lösung für die gebrochenen Workflow, der heute tritt auf, wenn Sie von einem Gerät zum anderen verschieben.Als ich zwischen meinem PC, Tablet und Telefon an einem typischen Tag wechseln, sollte meine Browser-Sitzung, Dokumente und Windows Anwendung stand natürlich für alle von ihnen fließen.Auf diese Weise würde ich weniger Zeit für Kontextwechsel und mehr Zeit auf tatsächliche Arbeit und Spiel verbringen.

In diesem Artikel zeige ich Ihnen, wie Sie eine einfache kontinuierlicher Client-Anwendung erstellen, die mehrere Geräte und Plattformen verteilt.Ich mache die neue Portable Klassenbibliotheken (PCLs), die zur Entwicklung einer Cross-Plattform-Anwendung und die Wolke verwenden – in bestimmten Windows Azure – AppFabric Service Bus —, die Kommunikation zwischen den Geräten behandeln.

Auf Ihrem Weg nach Hause …

Es ist am späten Nachmittag und ich bin bei der Arbeit versucht, den letzten Fehler schnell zu beheben, so dass ich Peak-Stunden Verkehr vermeiden können.Die unvermeidliche Anruf kommt: "Abholen Honig, auf Ihrem Weg Startseite können Sie einige Milch, Brot und Kichererbsen?" Ich auflegen, um den Speicher und erkennen, dass ich vergessen habe, was zu kaufen.Am Ende ich den Startseite Kopf mit Elementen haben wir bereits in der Speisekammer.Es ist frustrierend, und heutzutage die Lösung neigt dazu, viel hin und her Telefon anrufen: "Sagtest gefrorene Erbsen oder Kichererbsen du?" "Kichererbsen.Und während Sie dort sind, können Sie kaufen Toilettenpapier?"

Um unsere Ehe Spannungen um dieses besondere Problem lindern (die anderen müssen für einen weiteren Tag warten), werde ich eine einfache Anwendung namens "On Your Way Home", das läuft auf unserer Windows Phone-Geräten und Windows 8 Beta Tabletten und können meine Frau und mich leicht verfolgen unsere Einkaufsliste zu schreiben.Es wird uns halten beide informiert, in Echtzeit über Änderungen der Einkaufsliste, damit jederzeit wir wissen genau, was wir kaufen müssen.

Gegeben, die ein Smartphone rennend Fenster Telefon und ein Windows-8-basierten Tablet sind verschiedene Geräte mit unterschiedlichen Aromen von Microsoft.NET Framework und Windows, ich verwende PCLs abstrakt entfernt Plattform Unterschiede und ermöglichen es mir, so viel Anwendungslogik wie möglich, einschließlich aller teilen die der Kommunikation mit den Windows Azure – AppFabric Service Bus.Ich verwende auch das Model-View-ViewModel (MVVM)-Muster (bit.ly/GW7l) die Verwendung der gleichen Modelle und ViewModels aus unserer gerätespezifische Ansichten zu erleichtern.

Portable Klassenbibliotheken

In der Vergangenheit, Cross-Plattform-Entwicklung in der.NET Framework ist nicht einfach gewesen.Während die.NET Framework hatte großen Träume als eine plattformübergreifende Laufzeitumgebung, Microsoft hat nicht noch vollständig auf das Versprechen geliefert.Wenn Sie jemals versucht haben, liefern ein.NET Framework-basierte Anwendung oder Rahmen, die mehrere Geräte erstreckt, werden Sie bemerkt haben, dass ein paar Dinge in der Art und Weise.

Seitens der Common Language Runtime die Assembly factoring, Versionsverwaltung und Assemblynamen sind anders unter die.NET Plattformen.System.net.dll hinzu z. B. auf die.NET Framework, die Peer-to-Peer-Netzwerk-APIs enthält, bedeutet etwas ganz anderes auf Silverlight, wo es die Kernnetzwerkstacks enthält.Diese APIs auf finden die.NET Framework müssen Sie auf System.dll-Verweis.Die Versionen der Assembly sind nicht identisch; Silverlight nimmt 2.0.5.0 für Versionen 2.0 bis 4 2.0.0.0 und 4.0.0.0 für erlassen wurden.NET Framework-Versionen 2.0 bis 4.Diese Unterschiede haben, in der Vergangenheit eine Assembly, die kompiliert wurde für eine Plattform läuft auf einem anderen verhindert.

Auf der Visual Studio Seite gleich am Anfang müssen Sie entscheiden, welche Plattform Ziel — die.NET Framework, Silverlight oder Windows Phone.Sobald die Entscheidung getroffen wird, ist es äußerst schwer zu verschieben oder eine neue Plattform zu unterstützen.Zum Beispiel, wenn Sie bereits targeting sind die.NET Framework auf der.NET Framework und Silverlight bedeutet erstellen ein neues Projekt und entweder kopieren oder verknüpfen die vorhandenen Dateien in das Projekt.Wenn Sie Glück haben, können Sie Ihre Anwendung so angepasst haben, dass Plattform-spezifischen Teile problemlos ausgetauscht werden.Wenn nicht (und dies ist wohl eher), Sie werden müssen um # if Plattform Ihren Weg rund um jede Buildfehler bis Sie einen sauberen Bau haben.

Dies ist, wo das neue PCLs helfen können.PCLs, verfügbar als kostenloses Add-on zu Visual Studio 2010 (bit.ly/ekNnsN) und in Visual Studio 11 Beta integriert, bieten eine einfache Möglichkeit für mehrere Zielplattformen verwenden ein einzelnes Projekt.Sie können erstellen eine neue PCL, wählen Sie die Frameworks Ziel möchten (siehe Abbildung 1) und dem Schreiben von Code beginnen.Unter der Decke die PCL-Tools behandeln die API Unterschiede und IntelliSense zu filtern, so dass Sie nur Klassen und Member, die verfügbar sind und Arbeiten über alle Frameworks Sie ausgewählt haben.Die resultierende Assembly kann, ohne Änderungen, auf alle angegebenen Frameworks dann verwiesen und ausgeführt werden.

Portable Class Library Target FrameworksAbbildung 1 Portable-Klasse Bibliothek Zielframeworks

Lösung-Layout

Eine typische Möglichkeit um eine Cross-Plattform-app mit einem PCL zu organisieren ist, haben ein oder mehrere tragbare Projekte, die die freigegebenen Komponenten enthält, und Plattform-spezifische Projekte für jede Plattform, die diese Projekte verweist.Für diese Anwendung brauche ich zwei Visual Studio-Lösungen — erstellt in Visual Studio 2010 (OnYourWayHome.VS2010) mit meiner Windows Phone-app und in Visual Studio 11 (OnYourWayHome.VS11) mit meiner app Windows Metro-Stil erstellt wurde.Ich brauche mehrere Lösungen weil zum Zeitpunkt des Schreibens der Windows Phone SDK 7.1 nur über Visual Studio 2010 funktioniert, während die neuen Tools von Windows 8 verfügbar sind nur als Teil von Visual Studio 11.(Derzeit) keine einzige Version, die beide unterstützt.Verzweifeln Sie nicht, obwohl; ein neues Feature in Visual Studio 11 hilft mir hier.Ich bin in der Lage, die meisten Projekte in der früheren Version erstellt, ohne dass sie in das neue Format konvertieren zu öffnen.Dies ermöglicht es mir, haben ein einzelnes Projekt PCL und verweisen sie aus beiden Lösungen.

Zahlen 2 und 3 zeigen das Projektlayout für meine Anwendung.AufIhrem­WayHome.Core, ein PCL-Projekt enthält Modelle, Modelle anzeigen, allgemeine Dienste und Plattform Abstraktionen.AufIhrem­WayHome.ServiceBus, auch ein PCL-Projekt enthält portable Versionen von APIs, die auf Windows-Azure sprechen wird.Beide Projekte werden von der Lösung Visual Studio 2010 und Visual Studio 11 gemeinsam genutzt.OnYourWayHome.Phone und OnYourWayHome.Metro sind Plattform-spezifische Projekte für Windows Phone 7,5 und.NET für Metro-Style apps, beziehungsweise.Diese enthalten die gerätespezifische Ansichten (z. B. die Seiten in der Anwendung) und Implementierungen der Abstraktionen in OnYourWayHome.Core und OnYourWayHome.ServiceBus gefunden.

Windows Phone Project Layout in Visual Studio 2010Abbildung 2 Windows Phone-Projekt-Layout in Visual Studio 2010

Windows Metro-Style App Project Layout in Visual Studio 11Abbildung 3 Windows Metro-Style App Projekt Layout in Visual Studio 11

Konvertieren von vorhandene Bibliotheken in PCLs

Ich nachgeladen die Kommunikation mit Windows-Azure aus das Beispiel in Silverlight-basierten REST servicebus.codeplex.com und konvertiert es zu einem PCL-Projekt.Manche Bibliotheken sind leichter als andere zu konvertieren, aber Sie laufen unweigerlich in Situationen, wo einen bestimmten Typ oder die Methode nicht zur Verfügung steht.Hier sind einige typische Gründe, die eine bestimmte API in PCLs nicht unterstützt werden kann:

Die API ist nicht von traditionellen alle Plattformen implementiert.NET Framework Datei IOs, wie z. B. System.IO.File und System.IO.Directory, fallen in diese Eimer.Silverlight und Windows Phone der System.IO.IsolatedStorage-APIs verwenden (obwohl anders als die.NET Framework-Version), während die Windows 8 Metro-Style apps Windows.Storage verwenden.

Das API ist nicht kompatibel für alle Plattformen einige APIs aussehen dasselbe, aber es ist schwer oder unmöglich zu Code gegen sie in eine portable und kohärenter Weise schreiben.ThreadStaticAttribute, die statische Felder haben einen eindeutigen Wert für jeden Thread ermöglicht, ist ein Beispiel.Wenn sie auf die Windows Phone und die Xbox-Plattformen vorhanden ist, unterstützt weder ihre Laufzeiten.

API ist als veraltet oder Legacy diese APIs entweder Verhalten enthalten, das ist unwahrscheinlich, dass auf zukünftigen Plattformen vorhanden, oder sie haben durch neuere Technologien ersetzt wurden.BackgroundWorker ist ein Beispiel dafür; Es wurde durch Aufgabe und die neuen asynchronen Programmfeatures in Visual Studio 11 Beta ersetzt.

Wir Ran aus der Zeit die meisten APIs waren nicht mit Portabilität im Gedächtnis geschrieben.Wir verbringen eine erhebliche Menge an Zeit durchlaufen jedes API um sicherzustellen, dass es gegen in eine portierbare Weise programmiert werden kann.Dabei wird z. B. zwicken oder die API zu machen, portable hinzufügen.Wegen der Zeit und Aufwand, in der ersten Version des PCLs wir auf Visual Studio Gallery zur Verfügung gestellt, wir priorisiert die hochwertige, äußerst APIs verwendet.System.Xml.Linq.dll und System.ComponentModel.DataAnnotations.dll sind Beispiele für APIs, die nicht in dieser ersten Version verfügbar aber stehen jetzt in der Beta-Version von Visual Studio 11.

Es gibt ein paar verschiedene Möglichkeiten der Behandlung einer API, die in einem dieser Szenarien liegt.Manchmal gibt es ein einfacher Austausch.Close-Methoden (Stream.Close, TextWriter.Close- und So weiter) haben beispielsweise in PCL veraltet und durch Dispose ersetzt worden.In solchen Fällen ist es nur eine Frage der einen Aufruf an die ehemaligen durch letztere ersetzt.Aber manchmal ist ein wenig schwieriger und erfordert mehr Arbeit.Eine Situation, die ich traf während der Konvertierung der Service Bus APIs beteiligt die HMAC-SHA256 Hashcode-Standardanbieter.Es ist nicht verfügbar in einer PCL aufgrund der Unterschiede zwischen Windows Phone und Metro-Style apps Kryptographie.Windows Phone apps verwenden.NET-basierten APIs zum Verschlüsseln, entschlüsseln und Hashen von Daten, während Metro-Style apps die neue native Windows Runtime (WinRT) APIs verwenden.

Der Code Fehler, die insbesondere beim Erstellen nach die Konvertierung im folgenden war:

using (HMACSHA256 sha256 = new HMACSHA256(issuerSecretBytes))
{
  byte[] signatureBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(token));
  signature = Convert.ToBase64String(signatureBytes);
}

Um die Lücken zwischen der Telefon-Kryptografie-APIs und der WinRT-Kryptografie-APIs helfen, erfand ich eine Plattform Abstraktion, die Service Bus-Anforderung darstellt. In diesem Fall benötigt der Service Bus einen Weg, um einen HMAC SHA256-Hash zu berechnen:

public abstract class ServiceBusAdapter
{
  public static ServiceBusAdapter Current
  {
    get;
    set;
  }
  public abstract byte[] ComputeHmacSha256(byte[] secretKey, byte[] data);
}

Ich habe ServiceBusAdapter das portable Projekt, als auch eine statische Eigenschaft zum Festlegen der aktuellen Abstraktion, die später wichtig werden. Als Nächstes erstellt Windows Phone- und Windows-8-spezifische HMAC SHA256 Implementierungen dieser Abstraktion, und setzen Sie diese in ihre jeweiligen Projekte, wie in Abbildung 4.

Abbildung 4 HMAC SHA256 Implementierungen für Windows Phone und Windows 8

// Windows Phone implementation
public class PhoneServiceBusAdapter : ServiceBusAdapter
{
  public override byte[] ComputeHmacSha256(byte[] secretKey, byte[] data)
  {
    using (var cryptoProvider = new HMACSHA256(secretKey))
    {
      return cryptoProvider.ComputeHash(data);
    }
  }
}
// Windows 8 implementation
public class MetroServiceBusAdapter : ServiceBusAdapter
{
  private const string HmacSha256AlgorithmName = "HMAC_SHA256";
  public override byte[] ComputeHmacSha256(byte[] secretKey, byte[] data)
  {
    var provider = MacAlgorithmProvider.OpenAlgorithm(HmacSha256AlgorithmName);
    var key = provider.CreateKey(_secretKey.AsBuffer());
    var hashed = CryptographicEngine.Sign(key, buffer.AsBuffer());
    return hashed.ToArray();
  }
}

Beim Start in das Windows Phone-Projekt bootstrapped"ich dann" Service Bus durch Festlegen des Telefonspezifische Adapters als den aktuellen Adapter:

ServiceBusAdapter.Current = new PhoneServiceBusAdapter();

Ich tat das gleiche für die Windows-8-Projekt:

ServiceBusAdapter.Current = new MetroServiceBusAdapter();

Mit alles im Ort wechselte ich dann den ursprünglichen nicht-Kompilierung Code über den Adapter aufrufen:

var adapter = ServiceBusAdapter.Current;
byte[] signatureBytes = adapter.ComputeHmacSha256(issuerSecretBytes, Encoding.UTF8.GetBytes(token));

Zwar gibt es zwei verschiedene Möglichkeiten zum Berechnen des Hashs je nach Plattform, spricht das portable Projekt also mit beide mithilfe einer einzigen Oberfläche. Dies kann ein wenig Arbeit nach vorne, aber ich kann die Infrastruktur problemlos wiederverwenden, wie ich in weitere APIs ausführen, die Überbrückung zwischen den Plattformen benötigen.

As a Side Note habe ich eine statische Eigenschaft zuzugreifen und Registrieren des Adapters, der vorhandenen APIs verschieben auf über den Adapter erleichtert. Wenn Sie z. B. die verwaltete Erweiterbarkeit Framework (MEF), Einheit oder Autofac ein Dependency Injection-Framework verwenden, finden Sie, dass es natürlich ist zu den Plattform-spezifischen Adapter in den Container registrieren und haben den Container "injizieren den Adapter in portable Komponenten, die es brauchen".

Anwendungslayout

Meine shopping-Liste Anwendung, On Your Way Home, hat zwei einfache Ansichten: ShoppingListView, die die aktuellen Elemente auf der Einkaufsliste angezeigt; und AddGroceryItemView, die einem Benutzer ermöglicht, weitere Elemente zur Liste hinzufügen. Zahlen 5 und 6 die Windows Phone Versionen dieser Ansichten anzeigen.

ShoppingListView
Abbildung 5 ShoppingListView

AddGroceryItemView
Abbildung 6 AddGroceryItemView

ShoppingListView zeigt alle Elemente, die noch gekauft werden, mit der Idee, wie Sie rund um den Shop gehen, Sie jedes Element überprüfen wie Sie es in den Warenkorb hinzufügen. Nach dem Kauf der Elemente, wird durch Klicken auf Auschecken die aktivierten Elemente aus der Liste, die angibt, dass sie nicht mehr gekauft werden müssen getroffen werden. Geräte die gleiche Einkaufsliste sofort freigeben (gut, wie sofort, wie das Netzwerk dahinter ermöglicht) finden Sie unter Änderungen von einer anderen Person.

Die Ansichten, die in die Plattform-spezifische Projekte Leben, bestehen hauptsächlich aus XAML und haben sehr wenig Codebehind, die begrenzt den Umfang des Codes müssen Sie zwischen den beiden Plattformen zu duplizieren. XAML-Datenbindung verwenden, binden die Ansichten sich an tragbaren ViewModels, die bieten die Befehle und Daten, die die Ansichten laufen. Denn es keine gemeinsame UI-Framework, die auf allen Plattformen ausgeliefert wird gibt, können nicht PCL Projekte UI-spezifische APIs verweisen. Allerdings können wenn Rahmenbedingungen, die sie unterstützen, sie APIs nutzen, die normalerweise von ViewModels verwendet werden. Dazu gehören die grundlegenden Typen, die XAML-Datenbindung Arbeit, z. B. INotifyPropertyChanged, ICommand und INotifyCollectionChanged machen. Auch, obwohl das Framework WinRT XAML nicht sie unterstützt, System.ComponentModel.DataAnnotations und INotifyDataErrorInfo für Vollständigkeit hinzugefügt wurden, und auf diese Weise können benutzerdefinierte XAML Validierung Frameworks tragbare ViewModels/Modelle unterstützen.

Zahlen 7 und 8 zeigen Beispiele der View/ViewModel Interaktionen. Abbildung 7 zeigt die Steuerelemente auf der Fenster-Telefon-Version von AddGroceryItemView und ihre Bindungen. Diese Steuerelemente gebunden sind, gegen die Eigenschaften auf die AddGroceryItemViewModel, die sowohl die Windows Phone als auch die Windows 8 Projekte, geteilt wird, wie in gezeigt Abbildung 8.

Abbildung 7 AddGroceryItemView Steuerelemente für Fenster Telefon

<StackPanel>
  <TextBox Text="{Binding Name, Mode=TwoWay}"
           Width="459"
           Height="80" />
  <Button Command="{Binding Add}"
          Content="add"
          Margin="307,5,0,0" />
  <TextBlock Text="{Binding NotificationText}"
             Margin="12,5,0,0"/>
</StackPanel>

Abbildung 8 AddGroceryItemViewModel Klasse für Windows 8

public class AddGroceryItemViewModel : NavigatableViewModel
{
  private string _name;
  private string _notificationText;
  private ICommand _addCommand;
  [...]
  public ICommand AddCommand
  {
    get { return _addCommand ??
(_addCommand = new ActionCommand(Add)); }
  }
  public string Name
  {
    get { return _name ??
String.Empty; }
    set { base.SetProperty(ref _name, value, "Name"); }
  }
  public string NotificationText
  {
    get { return _notificationText ??
string.Empty; }
    set { base.SetProperty(ref _notificationText, value, "NotificationText"); }
  }
}

Ereignis auftreten

Auf Your Way Home basiert stark auf das Konzept der Veranstaltung Beschaffung (bit.ly/3SpC9h). Dies ist die Idee, dass alle Änderungen des Ansichtszustands zu einer Anwendung veröffentlicht und als eine Abfolge von Ereignissen gespeichert sind. In diesem Zusammenhang nicht Ereignis beziehen sich auf das, was definiert durch das c#-Schlüsselwort Event (obwohl die Idee dasselbe ist), sondern um konkrete Klassen, die eine einzelne Änderung für das System darstellen. Diese werden durch, was einen Ereignis-Aggregator genannt hat, der dann ein oder mehrere Handler benachrichtigt, die in Reaktion auf das Ereignis funktionieren veröffentlicht. (Finden Sie mehr über Ereignisaggregation, Shawn Wildermuth Artikel, "Composite Web Apps mit Prism," unter msdn.microsoft.com/magazine/dd943055.)

Das Ereignis, das ein Lebensmittelgeschäft-Element hinzugefügt wird, um die Einkaufsliste darstellt z. B. sieht in etwa wie in Abbildung 9.

Abbildung 9 Elementereignis hinzugefügt

// Published when a grocery item is added to a shopping list
[DataContract]
public class ItemAddedEvent : IEvent
{
  public ItemAddedEvent()
  {
  }
  [DataMember]
  public Guid Id
  {
    get;
    set;
  }
  [DataMember]
  public string Name
  {
    get;
    set;
  }
}

Die ItemAddedEvent-Klasse enthält Informationen über die Veranstaltung: in diesem Fall der Namen der das Lebensmittelgeschäft-Element, das hinzugefügt wurde und eine ID, die verwendet hat, um eindeutig darzustellen allgemeinverständlichen innerhalb eines shopping-Liste. Veranstaltungen sind auch mit [DataContract] markiert die macht es einfacher für sie auf dem Datenträger serialisiert oder über die Verbindung gesendet werden.

Dieses Ereignis wird erstellt und veröffentlicht, klickt der Benutzer auf die Schaltfläche hinzufügen, auf die AddGroceryItemView, wie in Abbildung 10.

Abbildung 10 das Ereignis veröffentlichen

public class AddGroceryItemViewModel : NavigatableViewModel
{
  private readonly IEventAggregator _eventAggregator;
  [...]
  // Adds an item to the shopping list
  private void Add()
  {
    var e = new ItemAddedEvent();
    e.Id = Guid.NewGuid();
    e.Name = Name;
    _eventAggregator.Publish(e);
    NotificationText = String.Format("{0} was added to the shopping list.", Name);
    Name = string.Empty;
  }
}

Beachten Sie, dass diese Methode nicht direkt jede Änderung auf der Einkaufsliste machen; einfach veröffentlicht die ItemAddedEvent an den Ereignis-Aggregator. Es ist die Verantwortung eines der Ereignishandler dieses Ereignis hören, etwas mit ihm zu tun. In diesem Fall eine Klasse namens ShoppingList abonniert und verarbeitet das Ereignis, wie in Abbildung 11.

Abbildung 11 die ShoppingList-Klasse

public class ShoppingList : IEventHandler<ItemAddedEvent>                                        
{
  public ShoppingList(IEventAggregator eventAggregator)
  {
    Requires.NotNull(eventAggregator, "eventAggregator");
    _eventAggregator = eventAggregator;
    _eventAggregator.Subscribe<ItemAddedEvent>(this);
  }
  [...]
  public ReadOnlyObservableCollection<GroceryItem> GroceryItems
  {
    get { return _groceryItems; }
  }
  public void Handle(ItemAddedEvent e)
  {
    var item = new GroceryItem();
    item.Id = e.Id;
    item.Name = e.Name;
    item.IsInCart = false;
    _groceryItems.Add(item);
  }
}
}

ItemAddedEvent veröffentlicht wird, ShoppingList erstellt eine neue GroceryItem mit den Daten aus dem Ereignis und die Einkaufsliste hinzugefügt.Die ShoppingListView, die indirekt an der gleichen Liste über seine ShoppingListViewModel gebunden ist, wird ebenfalls aktualisiert.Dies bedeutet, dass wenn der Benutzer wieder auf die Listenseite navigiert, die Elemente, die er gerade zu der Liste hinzugefügt wie erwartet angezeigt werden.Der Prozess der Entfernen eines Elements aus der Einkaufsliste, sind Hinzufügen eines Elements zu einem Warenkorb und Check-out die Karre, dass alle mit das gleichen Ereignis veröffentlichen/abonnieren-Muster behandelt.

Es mag zunächst wie eine Menge der Dereferenzierung für etwas so einfaches wie eine Einkaufsliste Elemente hinzufügen: die AddGroceryItemViewModel.Add-Methode veröffentlicht ein Ereignis in der IEventAggregator, die es auf der Unit, übergibt es die Einkaufsliste hinzu.Warum nicht die AddGroceryItemViewModel.Add-Methode einfach umgehen die IEventAggregator und fügen Sie die neuen GroceryItem direkt an der Unit?Ich bin froh, dass du fragst.Der Vorteil der Behandlung alle Änderungen am Ansichtszustand für das System als Veranstaltungen ist, dass es ermutigt die einzelnen Teile der Anwendung, sehr lose gekoppelt werden.Da Verleger und den Abonnenten nicht voneinander wissen, ist ein neues Feature in der Pipeline einfügen, wie Synchronisierung von Daten in und aus der Wolke, viel einfacher.

Synchronisieren von Daten in die Cloud

Ich habe behandelt die grundlegende Funktionen der Anwendung auf einem Gerät ausgeführt, aber es ist immer noch das Problem der immer der Änderungen ein Benutzers die Einkaufsliste zu anderen Geräten stellt, und umgekehrt.Dies ist, wo Windows Azure – AppFabric Service Bus kommt in.

Windows Azure – AppFabric Service Bus ist ein Feature, mit dem Anwendungen und Dienste problemlos miteinander über das Internet, die Komplexität der Navigation Kommunikation Hindernisse wie Firewalls und Network Address Translation (NAT) Geräte zu vermeiden sprechen kann.Es bietet Ruhe und Windows Communication Foundation (WCF)-HTTP-Endpunkte, die von Windows-Azure gehostet und befindet sich zwischen dem Verleger und dem Abonnenten.

Es gibt drei Möglichkeiten für die Kommunikation mit den Windows Azure – AppFabric Service Bus; für den Zweck meiner Anwendung werde ich jedoch nur Themen behandeln.Für einen vollständigen Überblick, check out "Eine Einführung in die Windows Azure – AppFabric Service Bus" bei bit.ly/uNVaXG.

Für Verlage, ein Service Bus Thema ähnelt einer großen Warteschlange in der Wolke (siehe Abbildung 12).Völlig unbekannt, wer zuhört, Verlage push Nachrichten zum Thema, wo sie ad infinitum statt sind, bis von einem Abonnenten angefordert.Um Nachrichten aus der Warteschlange zu erhalten, ziehen Abonnenten ein Abonnement, die filtert Nachrichten zum Thema veröffentlicht.Abonnements wirken wie eine bestimmte Warteschlange und Nachrichten entfernt ein Abonnement werden noch von anderen Abonnements gesehen werden, wenn sie ihre eigenen Filter einzuschließen.

Service Bus TopicAbbildung 12 Service Bus Thema

In On Your Way Home ist die AzureServiceEventHandler-Klasse die Brücke zwischen der Anwendung und den Service Bus.Ähnlich wie bei ShoppingList, implementiert es auch IEventHandler <T>, aber anstelle von bestimmten Ereignissen, AzureServiceEventHandlers beherrscht sie alle, wie in gezeigt Abbildung 13.

The AzureServiceEventHandler ClassAbbildung 13 die AzureServiceEventHandler-Klasse

public class AzureServiceBusEventHandler : DisposableObject, IEventHandler<IEvent>, IStartupService
{
  private readonly IAzureServiceBus _serviceBus;
  private readonly IAzureEventSerializer _eventSerializer;
  public AzureServiceBusEventHandler(IEventAggregator eventAggregator,
    IAzureServiceBus serviceBus, IAzureEventSerializer eventSerializer)
  {
    _eventAggregator = eventAggregator;
    _eventAggregator.SubscribeAll(this);
    _serviceBus = serviceBus;
    _serviceBus.MessageReceived += OnMessageReceived;
    _eventSerializer = eventSerializer;
  }
  [...]
  public void Handle(IEvent e)
  {
    BrokeredMessage message = _eventSerializer.Serialize(e);
    _serviceBus.Send(message);
  }
}

Jede Änderung, die ein Benutzer an den Staat auf der Einkaufsliste macht ist von AzureServiceBusEventHandler verarbeitet und direkt auf der Wolke geschoben. Weder AddGroceryItemViewModel, die das Ereignis veröffentlicht, noch Unit, die es auf dem lokalen Gerät behandelt, ist sich bewusst, dass dies geschieht.

Die Fahrt zurück aus der Wolke ist, wo eine Ereignis-basierte Architektur wirklich zahlt sich aus. Wenn der AzureServiceEventHandler erkennt, dass eine neue Nachricht auf dem Service-Bus (über das IAzureServiceBus.MessageReceived C#-Ereignis) eingegangen sind, es ist die Umkehrung der was es zuvor getan haben und deserialisiert die empfangene Nachricht zurück in ein Ereignis. Von hier, aus ruft es zurück über den Ereignis-Aggregator, wodurch es als käme das Ereignis von der Anwendung behandelt werden, wie in gezeigt veröffentlicht Abbildung 14.

Abbildung 14 Deserialisieren einer empfangenen Nachricht

public class AzureServiceBusEventHandler : DisposableObject, IEventHandler<IEvent>,
  IStartupService
{
  private readonly IAzureServiceBus _serviceBus;
  private readonly IAzureEventSerializer _eventSerializer;
  [...]
  private void OnMessageReceived(object sender, MessageReceivedEventArgs args)
  {
    IEvent e = _eventSerializer.Deserialize(args.Message);
    _eventAggregator.Publish(e);
  }
}

Die Unit ist nicht bewusst (noch kümmert es) über die Quelle des Ereignisses und Griffe, die denen der Service Bus/Wolke aus, als käme sie direkt von einem Benutzer Eingabe des. Es aktualisiert die Liste der Lebensmittel, wodurch wiederum die Ansichten gebunden an diese Liste auch aktualisiert werden.

Wenn Sie besondere Aufmerksamkeit widmen, bemerken Sie möglicherweise ein kleines Problem mit dem Workflow: Ereignisse, die in der Wolke vom lokalen Gerät gesendet bekommen das gleiche Gerät zurückkommen und Vervielfältigung der Daten verursachen. Schlimmer noch, kommen auch Änderungen an anderen, nicht verwandten Einkaufslisten zu diesem Gerät. Ich kenne nicht über Sie, aber ich bin ziemlich sicher, dass ich nicht anderen Menschen Ernährungsgewohnheiten, die auf meiner Einkaufsliste sehen wollen. Um dies zu verhindern, wird ein Service-Bus-Thema erstellt pro Liste, und ein Abonnement pro Gerät, die zum Thema hört. Wenn die Nachrichten vom Gerät zu dem Thema veröffentlicht werden, wird eine Eigenschaft mit die Geräte-ID zusammen mit den Nachrichten gesendet, der Abonnement-Filter verwendet, um Nachrichten auszuschließen, die von seinen eigenen Gerät kam. Abbildung 15 zeigt diesen Workflow.

Device-to-Device Workflow
Abbildung 15-Gerät-zu-Gerät-Workflow

Nachbereitung

Ich behandelt viel in diesem Artikel: Portable Klassenbibliotheken meine Lösung vereinfacht und erheblich verringert den Umfang des Codes, die ich brauchte, um für die zwei Zielplattformen schreiben. Auch, Ändern der Anwendungszustand über Ereignisse gemacht es sehr bequem dieses Staates mit der Wolke zu synchronisieren. Es gibt noch eine Menge, die ich Links, die jedoch ungesagt haben, dass Sie Faktor, wenn einen kontinuierlichen Client entwickeln wollen. Habe ich nicht darüber reden Offlineereignis Zwischenspeichern und Fault Toleranz (was passiert, wenn das Netzwerk nicht zur Verfügung wenn ich ein Ereignis veröffentlichen?), Zusammenführungskonflikte (was passiert, wenn ein anderer Benutzer eine Änderung, die Konflikte mit mir macht?), Wiedergabe (wenn ich ein neues Gerät an die Einkaufsliste anfügen, wie es aktualisiert?), Zutrittskontrolle (wie verhindere ich nicht autorisierte Benutzer Zugriff auf Daten, die sie sollten nicht?) und schließlich, Persistenz. Im Beispielcode für den Artikel speichern nicht die Anwendung die Einkaufsliste zwischen Starts. Ich lasse dies als eine Übung für Sie; Es könnte eine interessante Herausforderung sein, wenn Sie mit dem Code herumspielen möchten. Eine naive (oder eher die traditionellen) Weg des nahenden Persistenz möglicherweise zu einem Haken direkt in der Unit-Klasse, die GroceryItem Objekte als serialisierbar markieren und aus in einer Datei speichern. Vor diesen Weg gehen, aber zu stoppen und daran denken: Angesichts der Tatsache, dass die Unit bereits nativ Ereignisse verarbeitet und schon es egal ist, woher sie kommen, sieht Synchronisieren von Daten in und aus der Wolke überraschend speichern und Wiederherstellen von Daten von der Festplatte, nicht wahr?

David Kean ist ein Entwickler auf die.NET Framework-Team bei Microsoft, wo er im Team (Base Class Library, BCL arbeitet). Davor arbeitete er auf die oft beliebte aber auch sehr missverstanden FxCop-Tool von und seine Verwandten Geschwister, Visual Studio Codeanalyse. Ursprünglich aus Melbourne, Australien, ist er jetzt in Seattle, Washington, mit seiner Frau, Lucy, und drei Kinder, Jack, Sarah und Ben basiert. Er finden Blogging auf davesbox.com.

Dank der folgenden technischen Experten für die Überprüfung dieses Artikels: Nicholas Blumhardt und Immo Landwerth