Редактировал(а) Alexandr Fokin 2022/12/07 07:48

Последние авторы
1 [[Reflection | Рефлексия>>doc:Разработка.NET.C#.Рантайм и типы.Reflection | Рефлексия .WebHome]]
2
3 [[Expression tree>>doc:Разработка.NET.C#.Рантайм и типы.Expression tree | Деревья выражений.WebHome]]
4
5 runtime/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagLinkedList.cs
6 [[https:~~/~~/github.com/dotnet/runtime/blob/7bac4e8fa611eb02ac1bd27b97a8570cbf321437/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagLinkedList.cs>>https://github.com/dotnet/runtime/blob/7bac4e8fa611eb02ac1bd27b97a8570cbf321437/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagLinkedList.cs]]
7
8 ----
9
10 {{code language="c#"}}
11 public static class ActivityExtensions
12 {
13 private static readonly Action<Activity, ActivityLink> ActivityAddLink1;
14 private static readonly Action<Activity, ActivityLink> ActivityAddLink2;
15
16 static ActivityExtensions()
17 {
18 var activityType = typeof(Activity);
19 var linkType = typeof(ActivityLink);
20
21 var linksField = activityType.GetField(
22 name: "_links",
23 bindingAttr: BindingFlags.Instance | BindingFlags.NonPublic
24 )!;
25
26 var collectionType = linksField.FieldType;
27 var collectionAddMethod = collectionType.GetMethod(
28 name: "Add",
29 bindingAttr: BindingFlags.Instance | BindingFlags.Public
30 )!;
31
32
33 {
34 var constructorMethod = collectionType.GetConstructor(
35 types: linkType.OneItemArray()
36 )!;
37
38
39 ActivityAddLink2 = (a, e) =>
40 {
41 var parameter = ((object)e).OneItemArray();
42 var collection = linksField.GetValue(a);
43
44 if (collection == null)
45 {
46 collection = constructorMethod.Invoke(parameter);
47 linksField.SetValue(a, collection);
48 }
49 else
50 {
51 collectionAddMethod.Invoke(
52 collection,
53 parameter
54 );
55 }
56 };
57 }
58
59 {
60 var constructorMethod = collectionType.GetConstructor(
61 types: linkType.OneItemArray()
62 )!;
63
64
65 var activityParameter = Expression.Parameter(activityType);
66 var linkParameter = Expression.Parameter(linkType);
67
68
69 var collectionExp = Expression.Field(activityParameter, linksField);
70
71 var addExp = Expression.Call(collectionExp, collectionAddMethod, linkParameter);
72
73 var constructorExp = Expression.New(constructorMethod, linkParameter);
74 var constructorAndSetExp = Expression.Assign(collectionExp, constructorExp);
75
76
77 var addMethodLambda = Expression.Lambda<Action<Activity, ActivityLink>>(
78 body: addExp,
79 parameters: new ParameterExpression[] { activityParameter, linkParameter }
80 );
81 var createCollectionMethodLambda = Expression.Lambda<Action<Activity, ActivityLink>>(
82 body: constructorAndSetExp,
83 parameters: new ParameterExpression[] { activityParameter, linkParameter }
84 );
85
86
87 Action<Activity, ActivityLink> addMethod = addMethodLambda.Compile();
88 Action<Activity, ActivityLink> createCollectionMethod = createCollectionMethodLambda.Compile();
89
90
91
92 ActivityAddLink1 = (a, e) =>
93 {
94 if (a.Links.Any())
95 {
96 addMethod(a, e);
97 }
98 else
99 {
100 createCollectionMethod(a, e);
101 }
102 };
103 }
104 }
105
106 [Obsolete]
107 public static void AddLink(
108 this Activity activity,
109 in ActivityLink link
110 )
111 {
112 ActivityAddLink1(
113 activity,
114 link
115 );
116 }
117
118 public static void AddLink(
119 this Activity activity,
120 Activity linkActivity,
121 params (string Key, string Value)[] tags
122 )
123 {
124 var link = new ActivityLink(
125 linkActivity.Context,
126 new ActivityTagsCollection(
127 tags.Select(
128 e => new KeyValuePair<string, object?>(e.Key, e.Value)
129 )
130 )
131 );
132
133 AddLink(
134 activity,
135 link
136 );
137 }
138 }
139 {{/code}}