Comment savoir quand vous avez été chargé via XML Serialization?
Je suis en train de charger un arbre d'objets à l'aide de la sérialisation XML, et au moment où il va charger les objets, et la création de l'arbre tout à fait heureux. Ma question tourne autour du fait que ces classes de soutenir un niveau de vérification. Ce que j'aimerais être capable de faire est d'appeler une méthode sur chaque objet après qu'il a fini d'être chargé.
Pour les besoins de la discussion, supposons que j'ai une assez générique arbre d'objets de différentes classes à différents niveaux, tels que:
<Customer name="Foo Bar Inc.">
<Office IsHq="True">
<Street>123 Any Street</Street>
<Town name="Anytown">
<State name="Anystate">
<Country name="My Country" />
</State>
</Town>
</Office>
<Office IsHq="False">
<Street>456 High Street</Street>
<Town name="Anycity">
<State name="Anystate">
<Country name="My Country" />
</State>
</Town>
</Office>
</Customer>
Est-il de toute façon à l'aide de la valeur par défaut serialisers (De la même façon que vous pouvez créer des méthodes comme ShouldSerializeFoo
) pour déterminer quand le chargement est fini pour chaque objet?
Edit:
Je tiens à souligner que le cas évident d'exposer quelque chose de semblable à un OnLoaded()
méthode que je pourrait appel après deserialising, me frappe comme étant une "mauvaise chose à faire".
Edit2:
Pour l'amour de la discussion, ce est mon hack "approche", qui travaille pour le niveau de base, mais l'enfant de la Ville nœud considère toujours qu'il doit être enregistré avec les changements dans le monde réel, le modèle d'objet est beaucoup plus complexe, mais cela permettra au moins de la compilation, sans la nécessité pour la totalité du code source)
public class Office
{
[XmlAttribute("IsHq")]
public bool IsHeadquarters { get; set; }
[XmlElement]
public string Street { get; set; }
[XmlElement]
public Town Town { get; set; }
protected virtual void OnLoaded() {}
public static OfficeCollection Search()
{
OfficeCollection retval = new OfficeCollection();
string xmlString = @"
<Office IsHq='True'>
<Street>123 Any Street</Street>
<Town name='Anytown'>
<State name='Anystate'>
<Country name='My Country' />
</State>
</Town>
</Office>";
XmlSerializer xs = new XmlSerializer(retval.GetType());
XmlReader xr = new XmlTextReader(xmlString);
retval = (OfficeCollection)xs.Deserialize(xr);
foreach (Office thisOffice in retval)
{
thisOffice.OnLoaded();
}
return retval;
}
}
source d'informationauteur Rowland Shaw
Vous devez vous connecter pour publier un commentaire.
Hmmm... c'est pas encore assez, mais vous pourriez refactoriser votre désérialisation logique dans une classe dédiée qui pourra notifier à l'objet désérialisé qu'il est originaire de XML avant de le retourner à l'appelant.
Mise à jour: je pense que cela devrait être assez facile à faire, sans s'égarer trop loin de celle des modèles qui sont fixées par le cadre... vous auriez juste besoin de s'assurer que vous utilisez la CustomXmlSerializer. Les Classes qui ont besoin de cette notification juste besoin de mettre en œuvre IXmlDeserializationCallback
J'ai essayé la solution proposée par abatishchev mais comme souligné par les commentaires ci-dessous sa réponse, le
Deserialize
méthode dans la coutume sérialiseur ne semble jamais appelée.J'ai été en mesure d'obtenir ce travail par une surcharge de tous les différents
Deserialize
surcharges j'aurais besoin de sorte qu'il serait toujours appeler la méthode personnalisée.De cette façon, en fait je vois le
Deserialize
méthode appelé.Un toughie, depuis
XmlSerializer
ne prend pas en charge la sérialisation des événements de rappel. Est-il possible que vous pouvez utiliserDataContractSerializer
? Que nemais n'autorise pas les attributs (comme@name
ci-dessus).Autrement; vous pourriez mettre en œuvre
IXmlSerializable
mais c'est beaucoup de travail, et très sujettes à l'erreur.Autrement - la vérification de l'appelant grâce à la pile, mais c'est très fragile, et l'odeur des mûres.
Après perdre un peu de temps avec la première réponse, j'ai adopté le code de HotN de la poste, sauf pour
CheckForDeserializationCallbacks
:Cela permet à l'aide de la norme
[OnDeserialized]
.UPD. Mise à jour post récursive de marcher sur l'arbre d'objets.
- Je utiliser une méthode de fabrique, qui ajoutent plus logique après la structurées en XML objet désérialisé. Une telle logique comprend la restauration de la relation interne (enfant-parent, frère, sœur..) entre les membres de l'objet.
Dans mon cas, c'était une collection d'objets, donc utilisé une exception solution d'avoir à le modifier un peu
Et alors que tout fonctionne parfaitement
J'ai lutté un peu ainsi obtenir les solutions ci-dessus pour travailler. J'ai trouvé la solution la plus simple pour avoir mon
OnDeserialization()
rappels d'incendie lors de l'utilisation de XmlSerializer a été à la chaîne d'un appel à BinaryFormatter par la suite. Ma classe avait déjà unGetClone()
méthode donc c'était assez simple et nié toutes mes tentatives de primordial XmlSerializerLa solution retenue ne fonctionne pas pour moi non plus.
Afin de faire enfin fonctionner, j'ai dû modifier HotN la solution un peu.
En particulier, j'ai ajouté la
vérifier (en fonction: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.propertyinfo.getvalue), afin d'éviter une missmatching paramètres exception.
Aussi j'ai quelques propriétés qui ne sont pas censé être mappé. Je attribués à [XmlIgnore], mais la solution fournie encore traitées.
Mais l'ajout d'une case à cocher pour savoir si l'passées en paramètre un objet est null a fait le tour.