2010-10-20 3 views
3

Je gère l'état actuel de mon application WP7 dans les événements OnNavigatedFrom et To de sorte que si l'application est désactivée OU qu'elle accède à une page différente, elle enregistre l'état dans le service PhoneApplicationService intégré Etat. J'ai un ViewModel which I dump to the state simple pour faciliter la vie. Lorsque vous naviguez vers une page différente dans mon application, l'état est bien stocké et restaure bien (c'est-à-dire je suppose qu'il s'agit d'une sérialisation à ce stade). Cependant, quand je l'application (c'est-à-dire le bouton Démarrer) je reçois une erreur non gérée avec la sérialisation et la pile ne me donne aucune indication quant à pourquoi il échoue. J'ai essayé d'encapsuler l'appel réel dans un bloc try catch pour essayer de voir ce qui ne va pas mais cela n'aide pas - c'est quelque chose que le runtime fait différemment lors de la désactivation avec mon objet que lorsqu'il le stocke entre pagesComment déboguer une erreur de sérialisation dans l'application WP7 désactivée

Voici mon code:

protected override void OnNavigatedFrom(NavigationEventArgs args) 
{ 
    appService.State["TournamentViewModel"] = tournamentViewModel; 
    base.OnNavigatedFrom(args); 
} 

protected override void OnNavigatedTo(NavigationEventArgs args) 
{ 
    if (appService.State.ContainsKey("TournamentViewModel")) 
    { 
     tournamentViewModel = (TournamentViewModel)appService.State["TournamentViewModel"]; 
    } 
    base.OnNavigatedTo(args); 
} 

Ceci est l'erreur qui est généré - Je ne peux pas savoir où le problème est - comment puis-je déboguer ce mieux?

Exception Infos: Message: "SecurityException" InnerException: "Impossible d'évaluer l'expression"

StackTrace:

at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.CreateGetOnlyCollectionDataContract(Int32 id, RuntimeTypeHandle typeHandle, Type type) 
    at System.Runtime.Serialization.DataContract.DataContractCriticalHelper.GetGetOnlyCollectionDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type) 
    at System.Runtime.Serialization.DataContract.GetGetOnlyCollectionDataContractSkipValidation(Int32 id, RuntimeTypeHandle typeHandle, Type type) 
    at System.Runtime.Serialization.XmlObjectSerializerContext.GetDataContractSkipValidation(Int32 typeId, RuntimeTypeHandle typeHandle, Type type) 
    at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiType(XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType) 
    at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle) 
    at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerializeReference(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle) 
    at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark) 
    at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark) 
    at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) 
    at System.Runtime.Serialization.XmlFormatWriter.InternalSerialize(MethodInfo methodInfo, Object memberValue, Type memberType, Boolean writeXsiType, XmlObjectSerializerWriteContext context, XmlWriterDelegator xmlWriter) 
    at System.Runtime.Serialization.XmlFormatWriter.WriteValue(Type memberType, Object memberValue, Boolean writeXsiType, XmlObjectSerializerWriteContext context, XmlWriterDelegator xmlWriter) 
    at System.Runtime.Serialization.XmlFormatWriter.WriteMember(SerializingObject serObj, Int32 memberIndex, ClassDataContract derivedMostClassContract) 
    at System.Runtime.Serialization.XmlFormatWriter.WriteClass(CallStackElement`1 callStackElement) 
    at System.Runtime.Serialization.XmlFormatWriter.Serialize(XmlObjectSerializerWriteContext context) 
    at System.Runtime.Serialization.XmlFormatWriter.InitializeCallStack(XmlWriterDelegator xmlWriterDel, Object obj, XmlObjectSerializerWriteContext writeContext, DataContract contract) 
    at System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context) 
    at System.Runtime.Serialization.XmlObjectSerializerWriteContext.WriteDataContractValue(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) 
    at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle) 
    at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph) 
    at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph) 
    at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph) 
    at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(XmlDictionaryWriter writer, Object graph) 
    at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(Stream stream, Object graph) 
    at Microsoft.Phone.Shell.StreamPersister.Serialize(IDictionary`2 dictionary, IEnumerable`1 knownTypes) 
    at Microsoft.Phone.Shell.StreamPersister.Save(ShellPageManager shellPageManager, String key, IDictionary`2 dictionary, IEnumerable`1 knownTypes) 
    at Microsoft.Phone.Shell.PhoneApplicationService.FireDeactivated() 
    at Microsoft.Phone.Execution.NativeEmInterop.FireOnPause() 

Mise à jour: Par tâtonnement, j'ai trouvé le problème à la AppBar, qui ne semble pas être sérialisable. Je l'ai marqué avec [IgnoreDataMember] et il jette maintenant une erreur plus significative sur un different problem. Je voudrais toujours savoir s'il y a des moyens faciles d'attraper cette info ...

+0

Il est difficile de dire ce qui est différent sur la désactivation par rapport à votre navigation standard sans avoir un exemple réalisable. Il y a toutes sortes de raisons pour lesquelles l'objet pourrait être dans un état différent qui empêche la capacité de sérialiser correctement. –

Répondre

3

Rodney,

Ma compréhension est que lorsque vous mettez un objet dans l'un des deux dictionnaires de l'Etat (l'un des hors PhoneApplicationPage et l'autre hors de PhoneApplicationServices) il n'a pas immédiatement sérialisation ou deserialize. Si vous utilisez la page Page.State pour stocker des données, elle sérialise votre sac d'état lorsque vous quittez la page et désérialise lorsque vous revenez sur la page (plutôt que lorsque vous ajoutez ou lisez un objet dans le sac d'état).Si vous utilisez PhoneApplicationService.State, la sérialisation se produit lorsque vous tombstone et la désérialisation lorsque l'application est réactivée (bien que je ne sache pas si cela est lié à l'événement PhoneApplicationService.Activated ou non).

Page.State, en passant, ne permet pas le partage de données entre les pages. L'enregistrement sur PhoneApplicationService.State vous permet de le faire. IsolatedStorage.AppSettings semble gérer les problèmes de désérialisation en silence, donc je ne sais pas quand cela se produit. La sérialisation se produit cependant lorsque vous appelez Save().

James

2

Eh bien, comment votre ViewModel exprime la façon dont il est sérialisable? Personnellement, j'ai tendance à éviter la sérialisation potentiellement complexe: une option assez simple consiste à donner à votre ViewModel la possibilité de se convertir explicitement en/de XML, puis d'effectuer manuellement cette étape, en enregistrant un XDocument (ou sa représentation sous forme de chaîne)) dans l'état de l'application. De cette façon, il est facile de déboguer l'étape de sérialisation, voir le XML exact étant généré etc.

Bien sûr, l'utilisation de XML ici est accessoire - si vous pouvez facilement tout mettre dans une chaîne CSV, ce serait bien aussi. Tout ce que vous pouvez facilement inspecter en termes de la forme sérialisée avant en mettant dans l'état de l'application. Je me rends compte que cela contourne certains des avantages supposés de la sérialisation "automatique", mais j'ai rencontré assez de problèmes difficiles à diagnostiquer avec la sérialisation automatique des objets arbitraires que je ne pense pas que les avantages l'emportent sur les inconvénients.

+0

Merci Jon, en ce moment je ne fais rien de fantaisiste - ce dont je suis confus, c'est la façon dont ça marche quand on s'éloigne de la page mais pas quand on est tombé - n'est-ce pas la preuve que la classe est sérialisable? Il doit faire quelque chose de différent lors de la désactivation. Est-ce que la trace de la pile vous dit quelque chose? J'en ai googlé plusieurs parties sans joie - je ne sais vraiment pas par où commencer. Peut-être une autre question est - comment puis-je exclure une partie de la classe de cette sérilisation automatique? Je peux essayer de le trouver par processus d'élimination peut-être. – Rodney

+0

Est-il possible de publier votre définition de classe TournamentViewModel? – indyfromoz

+0

Merci, j'ai trouvé l'erreur - J'utilise une technique MVVM de créer le ApplicationBar dans la machine virtuelle, puis de liaison (comme vous ne pouvez pas lier à l'AppBar dans votre vue). Cela causait les problèmes (que j'ai trouvé par le processus d'élimination) donc je l'ai marqué avec [IgnoreDataMember] et il a passé ce problème. Mon PROCHAIN ​​problème est maintenant que la VM hérite de MVVMLight ViewModelBase qui n'a pas de constructeur public sans paramètre, donc la sérialisation échoue! http://stackoverflow.com/questions/3976170/issue-with-mvvmlight-viewmodelbase-public-parameterless-constructor-in-inherited – Rodney

Questions connexes