2011-12-19 11 views
16

Esiste un modo per scegliere i valori predefiniti degli attributi che non si trovano nel file xml durante la deserializzazione?
Se l'attributo mAge non è presente nel file xml, voglio utilizzare un valore predefinito di 18. È possibile?DataContract, valore DataMember predefinito

[DataContract] 
public class Person 
{ 
    public Person() 
    { 
    } 
    [DataMember(Name = "Name")] 
    public string mName { get; set; } 
    [DataMember(Name = "Age")] 
    public int mAge { get; set; } 
    [DataMember(Name = "Single")] 
    public bool mIsSingle { get; set; } 
}; 

Modifica per inserire la risposta.

[DataContract] 
public class Person 
{ 
    public Person() 
    { 
    } 
    [DataMember(Name = "Name")] 
    public string mName { get; set; } 
    [DataMember(Name = "Age")] 
    public int? mAge { get; set; } 
    [DataMember(Name = "Single")] 
    public bool? mIsSingle { get; set; } 

    [System.Runtime.Serialization.OnDeserialized] 
    void OnDeserialized(System.Runtime.Serialization.StreamingContext c) 
    { 
     mAge = (mAge == null ? 18 : mAge); // 18 is the default value 
    } 
} 

risposta

21

È possibile utilizzare [OnDeserialized]

Usare l'OnDeserializedAttribute quando è necessario fissare i valori su un oggetto deserializzato dopo che è stato deserializzati e prima che il grafico viene restituito.

[DataContract] 
public class Person 
    { 
    public Person() 
    { 
    } 
    [DataMember(Name = "Name")] 
    public string mName { get; set; } 
    [DataMember(Name = "Age")] 
    public int mAge { get; set; } 
    [DataMember(Name = "Single")] 
    public bool mIsSingle { get; set; } 



    [System.Runtime.Serialization.OnDeserialized] 
    void OnDeserialized(System.Runtime.Serialization.StreamingContext c) 
    { 
     mAge = (mAge == 0) ?18:mAge; 
    } 
    } 
} 

EDIT: Dal vostro Commenti

Per bool o int è possibile utilizzare nullable bool and nullable int quindi se questi l'età e gli attributi singoli mancano nel file XML allora sarà nullo pure.

qui è semplice campione ho preparato

using System.Runtime.Serialization; 
using System.ServiceModel; 
using MySpace; 
using System.ServiceModel.Channels; 
using System; 
namespace MySpace 
{ 

[DataContract] 
public class Person 
    { 
    public Person() 
    { 
    } 
    [DataMember(Name = "Name")] 
    public string mName { get; set; } 
    [DataMember(Name = "Age")] 
    public int? mAge { get; set; } 
    [DataMember(Name = "Single")] 
    public bool? mIsSingle { get; set; } 



    [System.Runtime.Serialization.OnDeserialized] 
    void OnDeserialized(System.Runtime.Serialization.StreamingContext c) 
    { 
     mAge = (mAge == null ? 18 : mAge); 
    } 
    } 
} 
[ServiceContract] 
public interface IService 
{ 
    [OperationContract] 
    Person Method(Person dd); 
} 

public class Service : IService 
{ 
    public Person Method(Person dd) 
    { 
    return dd; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
    string Url = "http://localhost:8000/"; 
    Binding binding = new BasicHttpBinding(); 
    ServiceHost host = new ServiceHost(typeof(Service)); 
    host.AddServiceEndpoint(typeof(IService), binding, Url); 
    host.Open(); 
    ChannelFactory<IService> fac = new ChannelFactory<IService>(binding); 
    fac.Open(); 
    IService proxy = fac.CreateChannel(new EndpointAddress(Url)); 
    Person d = new Person(); 
    d.mName = "BuzBuza"; 

    Console.WriteLine("Data before calling service " + (d.mAge == null ? " null " : d.mAge.Value.ToString())); 
    Console.WriteLine("Data before calling service " + (d.mIsSingle == null ? "null" : d.mIsSingle.Value.ToString())); 
    d = proxy.Method(d); 
    fac.Close(); 
    host.Close(); 
    Console.WriteLine("Data after calling service " + (d.mAge == null ? " null " : d.mAge.Value.ToString())); 
    Console.WriteLine("Data after calling service " + (d.mIsSingle == null ? "null" : d.mIsSingle.Value.ToString())); 

    Console.ReadLine(); 
    } 
} 
+0

Posso usare la tua risposta se voglio sovrascrivere il valore di un oggetto, perché quando il riferimento è impostato su null so che l'attributo non è presente nel file xml. Ma come posso sapere se un attributo booleano o int è presente nel file xml? Se il valore per un bolean è impostato su false o un int è impostato su 0. Non riesco a distinguere tra attributo e attributo non impostato impostato su valore C# predefinito. – BuzBuza

+0

Poiché la deserilizzazione proverà a impostare valori predefiniti per i dati mancanti in una determinata struttura, quindi l'unica opzione è verificare i valori validi, ad es. Come ho aggiornato la mia risposta e verificato se mAge == 0 quindi impostare il valore. –

+0

È possibile utilizzare i tipi nullable per aggirare int e null, controllare le mie ans aggiornate –

2

Questo dovrebbe funzionare.

[DataContract] 
public class Person 
    { 
    public Person() 
    { 
    } 
    [DataMember(Name = "Name")] 
    public string mName { get; set; } 
    [DataMember(Name = "Age")] 
    public int mAge = 18; 
    [DataMember(Name = "Single")] 
    public bool mIsSingle { get; set; } 
    }; 

Dare un'occhiata alla pagina this.

+0

No, questo non funziona (l'ho appena testato). Deserializer sovrascrive il valore predefinito, anche se tale valore non è presente in XML_. –

3

uso [OnDeserializing()]

e si imposta il valori prima della deserializzazione. Quindi non è necessario alcun controllo, che potrebbe andare storto: cosa succede se il mAge è stato serializzato per essere 0?

+0

Quando deserializzi i tipi semplici (ad esempio 'double') o le strutture, questo è il modo corretto. Prima della deserializzazione, i campi facoltativi vengono impostati su un valore predefinito specifico dell'app (o un valore non valido, ad esempio 'double.NaN'). La deserializzazione sovrascriverà tutti i valori dati nel file XML e ne lascerà inalterati gli altri. Dopo la deserializzazione non è possibile distinguere un valore zero "set da XML" e un valore zero "non impostato". –