Skip to content

Commit 6fd1230

Browse files
committed
Clean up DynamicDependencyAttribute usages
1 parent 6056cb3 commit 6fd1230

14 files changed

Lines changed: 639 additions & 22 deletions

File tree

src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/TypeDescriptor.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ private TypeDescriptor()
8585
[EditorBrowsable(EditorBrowsableState.Advanced)]
8686
public static Type InterfaceType
8787
{
88-
// TODO: replace this with DynamicallyAccessedMembersAttribute (https://github.com/dotnet/runtime/issues/37837)
89-
[DynamicDependency("#ctor", typeof(TypeDescriptorInterface))]
88+
[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
9089
get => typeof(TypeDescriptorInterface);
9190
}
9291

src/libraries/System.Data.Common/src/System/Data/SQLTypes/SqlXml.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ private static Func<Stream, XmlReaderSettings, XmlParserContext, XmlReader> Crea
128128

129129
private static MethodInfo CreateSqlReaderMethodInfo
130130
{
131-
[DynamicDependency("CreateSqlReader", typeof(System.Xml.XmlReader))]
132131
get
133132
{
134133
if (s_createSqlReaderMethodInfo == null)

src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -892,9 +892,6 @@ public PropertyFetch(Type? type)
892892
/// <summary>
893893
/// Create a property fetcher for a propertyName
894894
/// </summary>
895-
[DynamicDependency("#ctor(System.Type)", typeof(EnumeratePropertyFetch<>))]
896-
[DynamicDependency("#ctor(System.Type,System.Reflection.PropertyInfo)", typeof(RefTypedFetchProperty<,>))]
897-
[DynamicDependency("#ctor(System.Type,System.Reflection.PropertyInfo)", typeof(ValueTypedFetchProperty<,>))]
898895
public static PropertyFetch FetcherForProperty(Type? type, string propertyName)
899896
{
900897
if (propertyName == null)
@@ -949,6 +946,12 @@ public static PropertyFetch FetcherForProperty(Type? type, string propertyName)
949946
Logger.Message($"Property {propertyName} not found on {type}");
950947
return new PropertyFetch(type);
951948
}
949+
// Delegate creation below is incompatible with static properties.
950+
else if (propertyInfo.GetMethod?.IsStatic == true || propertyInfo.SetMethod?.IsStatic == true)
951+
{
952+
Logger.Message($"Property {propertyName} is static.");
953+
return new PropertyFetch(type);
954+
}
952955
Type typedPropertyFetcher = typeInfo.IsValueType ?
953956
typeof(ValueTypedFetchProperty<,>) : typeof(RefTypedFetchProperty<,>);
954957
Type instantiatedTypedPropertyFetcher = typedPropertyFetcher.GetTypeInfo().MakeGenericType(
@@ -966,6 +969,8 @@ public static PropertyFetch FetcherForProperty(Type? type, string propertyName)
966969

967970
private sealed class RefTypedFetchProperty<TObject, TProperty> : PropertyFetch
968971
{
972+
[DynamicDependency("get_TraceStateString", typeof(Activity))]
973+
[DynamicDependency("get_IsAllDataRequested", typeof(Activity))]
969974
public RefTypedFetchProperty(Type type, PropertyInfo property) : base(type)
970975
{
971976
Debug.Assert(typeof(TObject).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()));
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Diagnostics;
8+
using System.Diagnostics.Tracing;
9+
using System.Text;
10+
11+
/// <summary>
12+
/// Tests that the System.Diagnostics.DiagnosticSourceEventSource.TransformSpec.PropertyFetch.FetcherForProperty
13+
/// method works as expected when used in a trimmed application.
14+
/// </summary>
15+
internal class Program
16+
{
17+
public static int Main()
18+
{
19+
using var eventListener = new DiagnosticSourceEventListener();
20+
using var diagnosticListener = new DiagnosticListener("MySource");
21+
string activityProps =
22+
"-DummyProp" +
23+
";ActivityId=*Activity.Id" +
24+
";ActivityStartTime=*Activity.StartTimeUtc.Ticks" +
25+
";ActivityDuration=*Activity.Duration.Ticks" +
26+
";ActivityOperationName=*Activity.OperationName" +
27+
";ActivityIdFormat=*Activity.IdFormat" +
28+
";ActivityParentId=*Activity.ParentId" +
29+
";ActivityTags=*Activity.Tags.*Enumerate" +
30+
";ActivityTraceId=*Activity.TraceId" +
31+
";ActivitySpanId=*Activity.SpanId" +
32+
";ActivityTraceStateString=*Activity.TraceStateString" +
33+
";ActivityParentSpanId=*Activity.ParentSpanId" +
34+
";ActivityRootId=*Activity.RootId" +
35+
";ActivityTags=*Activity.Tags" +
36+
";ActivityLinks=*Activity.Links" +
37+
";ActivityIsAllDataRequested=*Activity.IsAllDataRequested" +
38+
";ActivityKind=*Activity.Kind" +
39+
";ActivityDisplayName=*Activity.DisplayName" +
40+
";ActivitySource=*Activity.Source" +
41+
";ActivityParent=*Activity.Parent" +
42+
";ActivityId=*Activity.Id" +
43+
";ActivityRecorded=*Activity.Recorded" +
44+
";ActivityEvents=*Activity.Events" +
45+
";ActivityBaggage=*Activity.Baggage" +
46+
";ActivityContext=*Activity.Context" +
47+
";ActivityActivityTraceFlags=*Activity.ActivityTraceFlags";
48+
eventListener.Enable(
49+
"MySource/TestActivity1.Start@Activity1Start:" + activityProps + "\r\n" +
50+
"MySource/TestActivity1.Stop@Activity1Stop:" + activityProps + "\r\n" +
51+
"MySource/TestActivity2.Start@Activity2Start:" + activityProps + "\r\n" +
52+
"MySource/TestActivity2.Stop@Activity2Stop:" + activityProps + "\r\n"
53+
);
54+
55+
Activity activity1 = new Activity("TestActivity1");
56+
activity1.SetIdFormat(ActivityIdFormat.W3C);
57+
activity1.TraceStateString = "hi_there";
58+
activity1.AddTag("one", "1");
59+
activity1.AddTag("two", "2");
60+
61+
var obj = new { DummyProp = "val" };
62+
63+
diagnosticListener.StartActivity(activity1, obj);
64+
return eventListener.EventCount == 1 ? 100 : -1;
65+
}
66+
67+
/// <summary>
68+
/// A helper class that listens to Diagnostic sources and send events to the 'EventWritten' callback.
69+
/// </summary>
70+
internal class DiagnosticSourceEventListener : EventListener
71+
{
72+
public DiagnosticSourceEventListener()
73+
{
74+
EventWritten += UpdateLastEvent;
75+
}
76+
77+
public int EventCount;
78+
public DiagnosticSourceEvent LastEvent;
79+
80+
/// <summary>
81+
/// Will be called when a DiagnosticSource event is fired.
82+
/// </summary>
83+
public new event Action<DiagnosticSourceEvent> EventWritten;
84+
85+
/// <summary>
86+
/// It is possible that there are other events besides those that are being forwarded from
87+
/// the DiagnosticSources. These come here.
88+
/// </summary>
89+
public event Action<EventWrittenEventArgs> OtherEventWritten;
90+
91+
public void Enable(string filterAndPayloadSpecs, EventKeywords keywords = EventKeywords.All)
92+
{
93+
var args = new Dictionary<string, string>();
94+
if (filterAndPayloadSpecs != null)
95+
args.Add("FilterAndPayloadSpecs", filterAndPayloadSpecs);
96+
EnableEvents(_diagnosticSourceEventSource, EventLevel.Verbose, keywords, args);
97+
}
98+
99+
/// <summary>
100+
/// Cleans this class up. Among other things disables the DiagnosticSources being listened to.
101+
/// </summary>
102+
public override void Dispose()
103+
{
104+
if (_diagnosticSourceEventSource != null)
105+
{
106+
DisableEvents(_diagnosticSourceEventSource);
107+
_diagnosticSourceEventSource = null;
108+
}
109+
}
110+
111+
#region private
112+
private void UpdateLastEvent(DiagnosticSourceEvent anEvent)
113+
{
114+
EventCount++;
115+
LastEvent = anEvent;
116+
}
117+
118+
protected override void OnEventWritten(EventWrittenEventArgs eventData)
119+
{
120+
bool wroteEvent = false;
121+
var eventWritten = EventWritten;
122+
if (eventWritten != null)
123+
{
124+
if (eventData.Payload.Count == 3 && (eventData.EventName == "Event" || eventData.EventName.Contains("Activity")))
125+
{
126+
Debug.Assert(eventData.PayloadNames[0] == "SourceName");
127+
Debug.Assert(eventData.PayloadNames[1] == "EventName");
128+
Debug.Assert(eventData.PayloadNames[2] == "Arguments");
129+
130+
var anEvent = new DiagnosticSourceEvent
131+
{
132+
SourceName = eventData.Payload[0].ToString(),
133+
EventName = eventData.Payload[1].ToString(),
134+
Arguments = new Dictionary<string, string>()
135+
};
136+
137+
var asKeyValueList = eventData.Payload[2] as IEnumerable<object>;
138+
if (asKeyValueList != null)
139+
{
140+
foreach (IDictionary<string, object> keyvalue in asKeyValueList)
141+
{
142+
keyvalue.TryGetValue("Key", out object key);
143+
keyvalue.TryGetValue("Value", out object value);
144+
if (key != null && value != null)
145+
anEvent.Arguments[key.ToString()] = value.ToString();
146+
}
147+
}
148+
eventWritten(anEvent);
149+
wroteEvent = true;
150+
}
151+
}
152+
153+
if (eventData.EventName == "EventSourceMessage" && 0 < eventData.Payload.Count)
154+
Debug.WriteLine("EventSourceMessage: " + eventData.Payload[0].ToString());
155+
156+
var otherEventWritten = OtherEventWritten;
157+
if (otherEventWritten != null && !wroteEvent)
158+
otherEventWritten(eventData);
159+
}
160+
161+
protected override void OnEventSourceCreated(EventSource eventSource)
162+
{
163+
if (eventSource.Name == "Microsoft-Diagnostics-DiagnosticSource")
164+
_diagnosticSourceEventSource = eventSource;
165+
}
166+
167+
EventSource _diagnosticSourceEventSource;
168+
#endregion
169+
}
170+
171+
/// <summary>
172+
/// Represents a single DiagnosticSource event.
173+
/// </summary>
174+
internal sealed class DiagnosticSourceEvent
175+
{
176+
public string SourceName;
177+
public string EventName;
178+
public Dictionary<string, string> Arguments;
179+
180+
public override string ToString()
181+
{
182+
StringBuilder sb = new StringBuilder();
183+
sb.AppendLine("{");
184+
sb.Append(" SourceName: \"").Append(SourceName ?? "").Append("\",").AppendLine();
185+
sb.Append(" EventName: \"").Append(EventName ?? "").Append("\",").AppendLine();
186+
sb.Append(" Arguments: ").Append("[").AppendLine();
187+
bool first = true;
188+
foreach (var keyValue in Arguments)
189+
{
190+
if (!first)
191+
sb.Append(",").AppendLine();
192+
first = false;
193+
sb.Append(" ").Append(keyValue.Key).Append(": \"").Append(keyValue.Value).Append("\"");
194+
}
195+
sb.AppendLine().AppendLine(" ]");
196+
sb.AppendLine("}");
197+
return sb.ToString();
198+
}
199+
}
200+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<Project DefaultTargets="Build">
2+
<Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.props))" />
3+
4+
<Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.targets))" />
5+
</Project>

src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.Generated.cs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
using System.Collections.Generic;
66
using System.Diagnostics;
7+
using System.Diagnostics.CodeAnalysis;
78
using System.Dynamic;
89
using System.Dynamic.Utils;
910
using System.Reflection;
10-
using System.Diagnostics.CodeAnalysis;
1111
using System.Threading;
1212

1313
namespace System.Linq.Expressions.Interpreter
@@ -160,17 +160,7 @@ private static CallInstruction FastCreate<T0, T1>(MethodInfo target, ParameterIn
160160
#endif
161161

162162
#if FEATURE_DLG_INVOKE
163-
// TODO: replace these with DynamicallyAccessedMembersAttribute (https://github.com/dotnet/runtime/issues/37837)
164-
[DynamicDependency("#ctor", typeof(ActionCallInstruction))]
165-
[DynamicDependency("#ctor", typeof(ActionCallInstruction<>))]
166-
[DynamicDependency("#ctor", typeof(ActionCallInstruction<,>))]
167-
[DynamicDependency("#ctor", typeof(ActionCallInstruction<,,>))]
168-
[DynamicDependency("#ctor", typeof(ActionCallInstruction<,,,>))]
169-
[DynamicDependency("#ctor", typeof(FuncCallInstruction<>))]
170-
[DynamicDependency("#ctor", typeof(FuncCallInstruction<,>))]
171-
[DynamicDependency("#ctor", typeof(FuncCallInstruction<,,>))]
172-
[DynamicDependency("#ctor", typeof(FuncCallInstruction<,,,>))]
173-
[DynamicDependency("#ctor", typeof(FuncCallInstruction<,,,,>))]
163+
[return: DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes.PublicConstructors)]
174164
private static Type GetHelperType(MethodInfo info, Type[] arrTypes)
175165
{
176166
Type t;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Linq.Expressions;
9+
10+
/// <summary>
11+
/// Tests that the System.Linq.Expressions.Interpreter.CallInstruction.GetHelperType
12+
/// method works as expected when used in a trimmed application.
13+
/// </summary>
14+
internal class Program
15+
{
16+
static int Main(string[] args)
17+
{
18+
for (int rank = 1; rank < 6; rank++)
19+
{
20+
Array arrayObj = Array.CreateInstance(typeof(string), Enumerable.Repeat(1, rank).ToArray());
21+
arrayObj.SetValue("solitary value", Enumerable.Repeat(0, rank).ToArray());
22+
ConstantExpression array = Expression.Constant(arrayObj);
23+
IEnumerable<DefaultExpression> indices = Enumerable.Repeat(Expression.Default(typeof(int)), rank);
24+
// This code path for the Compile call excercises the method being tested.
25+
Func<string> func = Expression.Lambda<Func<string>>(
26+
Expression.ArrayAccess(array, indices)).Compile(preferInterpretation: true);
27+
28+
if (func() != "solitary value")
29+
{
30+
return -1;
31+
}
32+
}
33+
34+
return 100;
35+
}
36+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
<Project DefaultTargets="Build">
3+
<Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.props))" />
4+
5+
<Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.targets))" />
6+
</Project>

src/libraries/System.Net.HttpListener/src/System/Net/Windows/CookieExtensions.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ internal static class CookieExtensions
1313
{
1414
private static Func<Cookie, string> s_toServerStringFunc;
1515

16-
[DynamicDependency("ToServerString", typeof(Cookie))]
1716
public static string ToServerString(this Cookie cookie)
1817
{
1918
s_toServerStringFunc ??= (Func<Cookie, string>)typeof(Cookie).GetMethod("ToServerString", BindingFlags.Instance | BindingFlags.NonPublic).CreateDelegate(typeof(Func<Cookie, string>));
@@ -23,7 +22,6 @@ public static string ToServerString(this Cookie cookie)
2322

2423
private static Func<Cookie, Cookie> s_cloneFunc;
2524

26-
[DynamicDependency("Clone", typeof(Cookie))]
2725
public static Cookie Clone(this Cookie cookie)
2826
{
2927
s_cloneFunc ??= (Func<Cookie, Cookie>)typeof(Cookie).GetMethod("Clone", BindingFlags.Instance | BindingFlags.NonPublic).CreateDelegate(typeof(Func<Cookie, Cookie>));
@@ -42,7 +40,6 @@ private enum CookieVariant
4240

4341
private static Func<Cookie, CookieVariant> s_getVariantFunc;
4442

45-
[DynamicDependency("get_Variant", typeof(Cookie))]
4643
public static bool IsRfc2965Variant(this Cookie cookie)
4744
{
4845
s_getVariantFunc ??= (Func<Cookie, CookieVariant>)typeof(Cookie).GetProperty("Variant", BindingFlags.Instance | BindingFlags.NonPublic).GetGetMethod(true).CreateDelegate(typeof(Func<Cookie, CookieVariant>));
@@ -55,7 +52,6 @@ internal static class CookieCollectionExtensions
5552
{
5653
private static Func<CookieCollection, Cookie, bool, int> s_internalAddFunc;
5754

58-
[DynamicDependency("InternalAdd", typeof(CookieCollection))]
5955
public static int InternalAdd(this CookieCollection cookieCollection, Cookie cookie, bool isStrict)
6056
{
6157
s_internalAddFunc ??= (Func<CookieCollection, Cookie, bool, int>)typeof(CookieCollection).GetMethod("InternalAdd", BindingFlags.Instance | BindingFlags.NonPublic).CreateDelegate(typeof(Func<CookieCollection, Cookie, bool, int>));
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Net;
6+
using System.Threading.Tasks;
7+
8+
namespace CookieExtensionsTest
9+
{
10+
/// <summary>
11+
/// Tests that the System.Net.CookieExtensions.Clone()
12+
/// method works as expected when used in a trimmed application.
13+
/// </summary>
14+
internal class Program
15+
{
16+
static async Task<int> Main(string[] args)
17+
{
18+
var helper = new TestHelper();
19+
HttpListenerResponse response = await helper.GetResponse();
20+
var cookie = new Cookie("name", "value");
21+
response.SetCookie(cookie);
22+
23+
// Cookies are cloned.
24+
cookie.Value = "value3";
25+
if (response.Cookies[0].Value != "value")
26+
{
27+
return -1;
28+
}
29+
30+
return 100;
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)