Scopo del gioco è creare un archiettura ben distribuita. Non ci interesserà scrivere del codice portabile e scalabile... le singole componenti dei singoli progetti potrebbero non esserlo, l'archiettura sarà però distribuibile su più macchine. Ecco un overview grafico di quello che andremo a realizzare nel corso di questo post.
Riassumento in modo verboso: Una console application (ReporterDashboard) permetterà ad un reporter di inviare ad un servizi editoriale (EditorialService) delle notizie. Le notizie saranno accodate e un _servizio_ (BroadcastingStudio) consumerà la coda delle notizie per pubblicarle in broadcast a tutte le Radio del gruppo connesse. Durante tutto il tragitto la notizie verrà arrichita con le informazioni di tracking. Le "radio" stamperanno notizie e tracking!
La nostra notizia transiterà come elemento XML per cui come prima cosa vado a definire lo schema del nostro messaggio.
<?xml version="1.0" encoding="utf-8"?>
<?xml:namespace prefix = xs /><xs:schema id=message xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="message">
<xs:complexType>
<xs:sequence>
<xs:element name="text" type="xs:string"></xs:element>
<xs:element name="tracking">
<xs:complexType>
<xs:sequence>
<xs:element name="stage" nillable="true" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="date" type="xs:dateTime" use="required"></xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Se vogliamo vederlo con uno schema più comprensibile ecco come lo mostra Visual Studio.
Che alla fine della fiera si traduce in un XML che suona più o meno così:
<?xml version="1.0"?>
<message>
<text>Hello World!</text>
<tracking>
<stage date="dd/mm/yyy">testo</stage >
<stage date="dd/mm/yyy">testo</stage >
</tracking>
</message>
Tutti componenti che andremo ad implementare useranno lo schema che abbiamo definito per implementare la struttura di classi per gestire la struttura con la serializzazione, si veda Tool Xsd e Xml Serialization.
Editorial Service
Il primo che implementeremo sarà il web service che ha il compito di riceve le notizie da mandare in pubblicazione.
A supporto del servzio implementeremo un AuthenticationHeader e un AuthenticationManger che serviranno per la gestione dell'authenticazione... non che il primo che passa per la strada possa pubblicare notizie :-p
public /*static */ class AuthenticationManager
{
public static bool Authenticate(string username, string password)
{
return (username == "markino" && password =="password");
}
}
[XmlType(Namespace = "http://markino.org/Authentication")]
public class AuthenticationHeader:SoapHeader
{
[XmlAttribute]
public string username;
[XmlAttribute]
public string password;
}
E per finire il servizio che ricevuto il messaggio aggiorna il Tracking e accoda su Message Queue. Per il mio test ho usato una coda privata precedentemente configurata. Ovviamente do per scontato che nel progetto dovranno essere incluse le classe generate dallo schema xsd (message e messageTrackingStage ).
[WebService(Namespace="http://markino.org/InteropGameChannel/EditorialService")]
public class EditorialService : System.Web.Services.WebService
{
public AuthenticationHeader authentication;
public EditorialService()
{
InitializeComponent();
}
[Component Designer generated code]
[WebMethod]
[SoapHeader("authentication")]
public void EnqueueNews(XmlElement element)
{
//authentica reporter ..
if(!AuthenticationManager.Authenticate(authentication.username, authentication.password))
{
throw new SoapException(
"Authentication failed!",
SoapException.ClientFaultCode,
HttpContext.Current.Request.Url.AbsoluteUri);
}
//legge elemento notizia ...
XmlNodeReader reader = new XmlNodeReader(element);
XmlSerializer ser = new XmlSerializer(typeof(message));
message message = (message)ser.Deserialize(reader);
//aggiorna il traking ...
ArrayList messageTrackingStages = new ArrayList(message.tracking);
messageTrackingStage trackingStage = new messageTrackingStage();
trackingStage.date = DateTime.Now;
trackingStage.Value = HttpContext.Current.Request.Url.AbsoluteUri;
messageTrackingStages.Add(trackingStage);
message.tracking = (messageTrackingStage[])messageTrackingStages.ToArray(typeof(messageTrackingStage));
//accoda la news ...
MessageQueue mq = new MessageQueue(@"FormatName:DIRECT=OS:MARKINO-MOBILE\private$\InteropQueue");
mq.Label = "Interop game message";
mq.Formatter = new XmlMessageFormatter();
mq.Send(message);
}
}
Le prossime componenti nei prossimi giorni :-p
posted @ mercoledì 20 aprile 2005 02:11