【问题标题】:Caliburn.Micro: Recovering from Exception in IResultCaliburn.Micro:从 IResult 中的异常中恢复
【发布时间】:2011-02-02 22:57:14
【问题描述】:

这也发布在Caliburn.Micro discussions。我真的在寻找最佳解决方法的建议和意见。

假设我有以下操作

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

StationSave 是一个简单 (WCF) 服务调用的 IResult 包装器。服务使用 FaultContract/FaultException 处理失败。

在发生故障时,需要通知用户,并且 FaultContract 将包含一些关于出错原因的有用信息。目前,Save 结果捕获异常并将其插入到 Completed 事件的 ResultCompletionEventArgs 中。通过这样做,由管道创建的 SequentialResult 被取消(由于错误),从而使屏幕处于忙碌状态。

我真正想要的是关于从错误中恢复(删除忙碌状态)并通知用户的最佳方法的想法(我有几个 IResult 实现,用于我想使用的不同样式的通知)过错合同中提供的详细信息。通过附加到我的 VM 中的 Completed 事件,我可以得到错误,但此时我不再处于 Action 管道的上下文中,所以我想使用任何 IResults(MakeNotBusy 和我的显示通知实现)我必须手动执行(我必须新建我自己不想做的 ActionExecutionContext)。

我从here 中查看了 Marco Amendola 的 Caliburn.Micro 救援过滤器,但我再次无法从 Rescue 方法传回 IResults。

我是否遗漏了一些明显的东西?其他人如何处理这种情况?

【问题讨论】:

    标签: c# silverlight silverlight-4.0 caliburn.micro


    【解决方案1】:

    Rob EisenbergMarco Amendola 都在CodePlex forum 中提供了可能的解决方案。

    我选择从他的filters implementation 中提取 Marco 的RescueAttribute 并稍微修改它以允许从救援方法执行进一步的IResult。这是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;
        }
    }
    

    这允许在我的虚拟机中进行以下操作:

    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>();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-28
      • 2016-05-19
      • 1970-01-01
      • 2019-01-28
      • 2017-12-26
      • 1970-01-01
      相关资源
      最近更新 更多