我们利用注册的ActivityListener在Activity终止时将Activity相关跟踪信息(操作名称、SpanId、ParentId、执行时间和Tag)打印在控制台上,具体输出如下所示 。

文章插图
二、CallerArgumentExpressionAttributeCallerArgumentExpressionAttribute特性里利用目标参数将当前方法调用的某个参数(构造函数的参数表示该参数的名称)的表达式保存下来 。如果指定的是一个变量(或者参数),捕获到的就是变量名 。比如我们定义了如下这个用来验证参数并确保它不能为Null的ArgumentNotNull<T> 。除了第一个表示参数值的argumentValue参数,它还具有一个表示参数名的argumentName参数,抛出的ArgumentNullException异常的参数名就来源于此 。
public static class Guard{ public static T ArgumentNotNull<T>(T argumentValue, [CallerArgumentExpression("argumentValue")] string argumentName = "") where T:class { if (argumentValue is null) throw new ArgumentNullException(argumentName); return argumentValue; }}我们修改了Invoker的构造函数,并按照如下的方式添加了针对输出参数(ActivitySource对象)的验证,以避免后续抛出NullReferenceException异常 。可以看出,我们调用ArgumentNotNull方法时并没有执行表示参数名称的第二个参数 。
var invoker = new Invoker(null);public class Invoker{ private readonly ActivitySource _activitySource; public Invoker(ActivitySource activitySource) => _activitySource = Guard.ArgumentNotNull(activitySource); ...}如果我们按照如上的方式调用Invoker的构造函数,并将Null作为参数,此时会抛出如下的异常,可以看到抛出的ArgumentNullException异常被赋予了正确的参数名 。

文章插图
三、CallerFilePathAttribute &CallerLineNumberAttributeCallerFilePathAttribute 和CallerLineNumberAttribute特性会将源代码的两个属性赋值给目标参数 。具体来说,前者会将当前源文件的路径绑定到目标参数,后者绑定的则是当前执行代码在源文件中的行数 。下面的代码为StartNewActivity扩展方法额外添加了两个参数,并标注了如上两个特性,我们将对应的参数值作为Tag添加到创建的Activity中 。
public static class Extensions{ public static Activity? StartNewActivity( this ActivitySource activitySource, ActivityKind kind = ActivityKind.Internal, [CallerMemberName] string name = "", [CallerFilePath] string? filePath = default, [CallerLineNumber] int lineNumber = default) => activitySource .StartActivity(name: name, kind: kind) ?.AddTag("CallerFilePath", filePath) ?.AddTag("CallerLineNumber", lineNumber);}再次执行我们的程序,控制台上就会输出添加的两个Tag 。
【几个Caller-特性的妙用】
经验总结扩展阅读
- 试述羽毛球运动的特点与锻炼价值
- 心理阴毒人的特征
- 烟斗合页什么牌子好?
- 怎么查看qq空间特别关心
- 萨米特抛光瓷砖怎么样?
- 去越南必买的十件东西,值得买的越南特产排名,越买越心动
- 剑南春52度有几种版本_剑南春分几个档次
- 贵州饮食特点
- 无花果一天最多吃几个
- 马超的性格有什么特点