Версия 1.2 от Alexandr Fokin на 2022/12/06 17:44

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