2011-02-02 1 views
2

Ceci a été publié au Caliburn.Micro discussions également. Je suis vraiment à la recherche de conseils et d'opinions sur la meilleure façon de résoudre.Caliburn.Micro: Récupération de l'exception dans IResult

Dire que j'ai l'action suivante

public IEnumerable<IResult> SaveStation() 
{ 
    yield return Busy.MakeBusy(); 
    yield return new StationSave(_station); 
    yield return Busy.MakeNotBusy(); 
    yield return Show.Tab<StationBrowseViewModel>(); 
} 

StationSave est une enveloppe iResult autour d'un appel de service simple (WCF). Le service utilise FaultContract/FaultException pour les échecs.

En cas de panne, l'utilisateur doit être averti et le FaultContract contiendra des informations utiles sur ce qui s'est passé. Actuellement, le résultat Enregistrer intercepte l'exception et l'insère dans ResultCompletionEventArgs de l'événement Completed. Ce faisant, le SequentialResult créé par le pipeline est annulé (en raison de l'erreur), laissant ainsi l'écran dans un état Occupé. Ce que je suis vraiment après est des idées sur la meilleure façon de récupérer de l'erreur (supprimer l'état occupé) et notifier l'utilisateur (j'ai quelques implémentations IResult pour différents styles de notification que je voudrais utiliser) des détails fournis dans le contrat de faute. En attachant à l'événement Completed dans ma VM, je peux obtenir l'erreur, mais à ce stade, je ne suis plus dans le contexte du pipeline Action, donc je souhaite utiliser les IResults que je voudrais utiliser (MakeNotBusy et ma mise en œuvre de la notification show) exécuter manuellement (et je devrais ajouter mon propre ActionExecutionContext que je ne veux pas faire).

J'ai jeté un oeil au filtre de sauvetage de Marco Amendola pour Caliburn.Micro de here, mais encore une fois je ne peux pas renvoyer IResults de la méthode Rescue.

Ai-je manqué quelque chose d'évident? Comment les autres gèrent-ils cette situation?

Répondre

1

Les deux Rob Eisenberg et Marco Amendola ont fourni des solutions possibles dans le CodePlex forum.

J'ai choisi de prendre le RescueAttribute de Marco à partir de son filters implementation et de le modifier légèrement pour permettre l'exécution d'autres IResult de la méthode de sauvetage. Ceci est le changement nécessaire pour RescueAttribute.HandleException

protected override bool HandleException(ActionExecutionContext context, 
             Exception ex) 
{ 
    var method = context.Target 
         .GetType() 
         .GetMethod(MethodName, new[] { typeof(Exception) }); 
    if (method == null) return false; 

    try 
    { 
     var result = method.Invoke(context.Target, new object[] { ex }); 

     if (result is bool) 
      return (bool) result; 

     if (result is IResult) 
      result = new[] { result as IResult }; 
     if (result is IEnumerable<IResult>) 
      Coroutine.Execute(((IEnumerable<IResult>) result).GetEnumerator(), context); 
     else if (result is IEnumerator<IResult>) 
      Coroutine.Execute(((IEnumerator<IResult>) result), context); 

     return true; 
    } 
    catch 
    { 
     return false; 
    } 
} 

ce qui permet ce qui suit dans ma VM:

public IEnumerable<IResult> Rescue(Exception ex) 
{ 
    yield return Busy.MakeNotBusy(); 
    // in practice pass exception details through to notification 
    yield return new NotificationPopup("Save station failed"); 
} 

[Rescue] 
public IEnumerable<IResult> SaveStation() 
{ 
    yield return Busy.MakeBusy(); 
    yield return new StationSave(_station); 
    yield return Busy.MakeNotBusy(); 
    yield return Show.Tab<StationBrowseViewModel>(); 
} 
Questions connexes