La soluzione più immediata sarebbe quella di avere die metodi, uno per la persona fisica che stampa nome e cognome e l'altra che stampa la ragione sociale. Sebbene questo sia un caso del tutto banale, che succederebbe se le opzioni fossero 10, 20 o di più ancora ? Sarebbe impraticabile.
L'alternativa consiste nell'utilizzare un elemento di scelta (choice). Immaginiamo quindi di avere due classi:
public class PersonaFisica
{
public string Nome;
public string Cognome;
}
public class PersonaGiuridica
{
public string RagioneSociale;
}
possiamo mappare le classi su un'unica proprietà:
[XmlType(Namespace="urn:peway:datatypes")]
public class Contatto
{
public string CodiceFiscale;
[XmlIgnore()]
public TipoPersona Tipo;
[XmlChoiceIdentifier("Tipo")]
[XmlElement("PersonaFisica", typeof(PersonaFisica))]
[XmlElement("PersonaGiuridica", typeof(PersonaGiuridica))]
public object Persona;
}
dove TipoPersona è un enumerato:
public enum TipoPersona
{
PersonaFisica,
PersonaGiuridica
}
in questo modo, stiamo dicendo al serializzatore XML che la proprietà Persona può essere sia PersonaGiuridica che PersonaFisica. L'attributo XmlChoiceIdentifierAttrbute è usato semplicemente per informare quale classe stiamo usando attraverso un enumerato. Il deserializzatore, quando arriva il messaggio SOAP andrà a verificare di che tipo è Persona e lo mapperà sulla classe corrispondente.
Diventa quiandi abbastanza semplice stampare il nominativo in base al valore contenuto dall'enumerato:
[WebService(Namespace="urn:peway:services")]
public class Contatti
{
[WebMethod]
public string StampaNominativo(Contatto contatto)
{
switch(contatto.Tipo)
{
case TipoPersona.PersonaFisica:
PersonaFisica pf = (PersonaFisica)contatto.Persona;
return string.Concat(pf.Nome, " ", pf.Cognome);
case TipoPersona.PersonaGiuridica:
PersonaGiuridica pg = (PersonaGiuridica)contatto.Persona;
return pg.RagioneSociale;
default:
return "Nessuna persona identificabile";
}
}
}