我在PolicyRegistry中有以下策略可以全局重用:
var fallbackPolicy = Policy
.Handle<DrmException>().OrInner<DrmException>()
.Fallback(
fallbackAction: () => { //should commit or dispose the transaction here using a passed in Func or Action },
onFallback: (exception) => { Log.Error().Exception(exception).Message($"Exception occurred, message: {exception.Message}.").Write(); }
);
我有以下代码,我想在{:1}中实现fallbackPolicy
:
if(Settings.DRM_ENABLED)
drmManager.ExecuteAsync(new DeleteUser(123).Wait();//HTTP Call, throws DrmException if unsuccessful
//in some cases, there is an if(transaction == null) here (if transaction was passed as a parameter and needs to be committed here)
transaction.Commit();//if not thrown - commits the transaction
我希望它看起来像这样:
var fallbackPolicy = Policy
.Handle<DrmException>().OrInner<DrmException>()
.Fallback(
fallbackAction: (transaction) => { transaction.Dispose(); },
onFallback: (exception) => { Log.Error().Exception(exception).Message($"Exception occurred, message: {exception.Message}.").Write(); }
);
fallbackPolicy.Execute(() => drmManager.ExecuteAsync(new DeleteUser(123).Wait(), transaction)
据我所知,fallbackPolicy.Execute
执行Action / Func要么成功,在这种情况下fallbackPolicy
没有被击中或失败,在这种情况下fallbackPolicy
使用一些预定义的fallbackAction
启动。
我想要做的是在执行策略时传入两个处理程序(onFail(transaction)
处理事务和onSuccess(transaction)
提交事务)。有没有更简单的方法来做它而不是包装它或使用Polly的上下文?
答案 0 :(得分:2)
感觉这里有几个单独的问题:
我将分别回答这些问题,为您提供一个完整的工具包来构建您自己的解决方案 - 以及未来的读者 - 但您可能不需要这三个来实现您的目标。如果您只是想要解决方案,请切至 3。。
<强> 1。如何让集中定义的FallbackPolicy做一些动态的事情?
对于集中定义的任何策略,是Context
是您可以传递特定于该执行的内容的方式。参考文献:discussion in a Polly issue; blog post
你的部分q似乎围绕着FallbackPolicy
两个日志;并处理交易。所以...
<强> 2。如何让一个FallbackPolicy做两件事?
你可以传递一些动态的东西(每个上面)。另一种选择是使用两种不同的回退策略。你可以use the same kind of policy multiple times in a PolicyWrap。因此,您可以定义集中存储的FallbackPolicy
来执行日志记录,并保持简单,非动态:
var loggingFallbackPolicy = Policy
.Handle<DrmException>().OrInner<DrmException>()
.Fallback(fallbackAction: () => { /* maybe nothing, maybe rethrow - see discussion below */ },
onFallback: (exception) => { /* logging; */ });
然后,您可以在本地定义另一个FallbackPolicy
以在失败时回滚事务。由于它是在本地定义的,因此您可能只需使用闭包将transaction
变量传递到其fallbackAction:
(在这种情况下,您不必使用Context
)。
注意:如果在FallbackPolicy
中使用两个PolicyWrap
,则需要进行内部FallbackPolicy
重新渲染 (不是吞下)处理过的异常,以便外部FallbackPolicy
也处理它。
回复:
我想要做的是传入两个处理程序(
onFail(transaction)
处理事务和提交事务的onSuccess(transaction)
没有任何政策可以提供成功的特殊处理,但是:
第3。在Polly的混合体中,我如何才能在整体失败方面做到一件事,在另一件事上取得整体成功呢?
使用.ExecuteAndCapture(...)
。这会返回PolicyResult
,其中包含属性.Outcome == OutcomeType.Successful
或OutcomeType.Failure
(以及其他信息:请参阅documentation)
总体而言,如:
var logAndRethrowFallbackPolicy = Policy
.Handle<DrmException>().OrInner<DrmException>()
.Fallback(fallbackAction: (exception, context, token) => {
throw exception; // intentional rethrow so that the 'capture' of ExecuteAndCapture reacts. Use ExceptionDispatchInfo if you care about the original call stack.
},
onFallback: (exception, context) => { /* logging */ });
在执行现场:
PolicyResult result = myPolicies.ExecuteAndCapture(() => ... ); // where myPolicies is some PolicyWrap with logAndRethrowFallbackPolicy outermost
if (result.Outcome == OutcomeType.Successful)
{ transaction.Commit(); }
else
{ transaction.Dispose(); }