-
Notifications
You must be signed in to change notification settings - Fork 50
控制方法执行
ihourglass edited this page Aug 9, 2024
·
2 revisions
在OnEntry
中可以通过修改MethodContext.Arguments
中的元素来修改方法的参数值,为了明确你是想要修改方法参数,还需要将MethodContext.RewriteArguments
设置为true
来确认修改。
public class DefaultValueAttribute : MoAttribute
{
public override void OnEntry(MethodContext context)
{
context.RewriteArguments = true;
// 判断参数类型最好通过下面ParameterInfo来判断,而不要通过context.Arguments[i].GetType(),因为context.Arguments[i]可能为null
var parameters = context.Method.GetParameters();
for (var i = 0; i < parameters.Length; i++)
{
if (parameters[i].ParameterType == typeof(string) && context.Arguments[i] == null)
{
context.Arguments[i] = string.Empty;
}
}
}
}
public class Test
{
// 当传入null值时将返回空字符串
[DefaultValue]
public string EmptyIfNull(string value) => value;
}
OnEntry
的执行时机是在执行方法前,有一些需求场景可能会希望在OnEntry
中做参数验证或身份验证等操作,在验证失败后跳过实际方法执行,直接返回,这也就是方法执行拦截。在OnEntry
中可以通过MethodContext
的ReplaceReturnValue
方法设置返回值,然后在OnEntry
执行完毕后就会用ReplaceReturnValue
设置的返回值作为方法的返回值直接返回。当然,你也可以在OnEntry
中直接抛出异常来阻止实际方法调用:
public class MockAttribute : MoAttribute
{
public override void OnEntry(MethodContext context)
{
// 如果方法无返回值(void),直接传入null即可
context.ReplaceReturnValue(this, mockValue);
}
}
在方法执行成功后,如果对实际的返回值不满意,可以直接在OnSuccess
中通过MethodContext
的ReplaceReturnValue
方法替换方法返回值:
public class DefaultResultAttribute : MoAttribute
{
public override void OnSuccess(MethodContext context)
{
// 如果方法无返回值(void),直接传入null即可
context.ReplaceReturnValue(this, context.ReturnValue ?? defaultValue);
}
}
在方法发生抛出异常后,可以在OnException
中通过调用MethodContext
的HandledException
方法表明异常已处理并设置返回值:
public class MuteExceptionAttribute : MoAttribute
{
public override void OnException(MethodContext context)
{
// 如果方法无返回值(void),直接传入null即可
context.HandledException(this, defaultValue);
}
}
重试功能可以在遇到指定异常或者返回值非预期值的情况下重新执行当前方法,实现方式是在OnException
和OnSuccess
中设置MethodContext.RetryCount
值,在OnException
和OnSuccess
执行完毕后如果MethodContext.RetryCount
值大于0那么就会重新执行当前方法。
internal class RetryAttribute : MoAttribute
{
public override void OnEntry(MethodContext context)
{
// 初始化重试次数
context.RetryCount = 3;
}
public override void OnException(MethodContext context)
{
// 出现异常减少一次重试次数,当RetryCount减到0时,表示达到重试次数上限,不再重试
context.RetryCount--;
}
public override void OnSuccess(MethodContext context)
{
if (context.ReturnValue != ABC)
{
// 结果非预期减少一次重试次数,当RetryCount减到0时,表示达到重试次数上限,不再重试
context.RetryCount--;
}
else
{
// 结果达到预期,直接将重试次数设置为0,不再进行重试
context.RetryCount = 0;
}
}
}
// 应用RetryAttribute后,Test方法将会重试3次
[Retry]
public void Test()
{
throw new Exception();
}
使用重试功能需要注意以下几点:
- 在通过
MethodContext.HandledException()
处理异常或通过MethodContext.ReplaceReturnValue()
修改返回值时会直接将MethodContext.RetryCount
置为0,因为手动处理异常和修改返回值就表示你已经决定了该方法的最终结果,所以就不再需要重试了 -
MoAttribute
的OnEntry
和OnExit
只会执行一次,不会因为重试而多次执行
针对异常处理重试的场景,作者创建了一个独立项目 Rougamo.Retry ,如果只是针对某种异常进行重试操作可以直接使用 Rougamo.Retry