Skip to content

Commit 118eee9

Browse files
authored
DataContractSerialization doesn't work with TrimMode - link (#42824)
DataContractSerialization has some Reflection "shim" methods that the ILLinker can't see through. This causes critical methods to be trimmed and applications to fail. These methods were put in place in .NET Core 1.0 when the full Reflection API wasn't available. The fix is to remove these "shim" Reflection APIs and use Reflection directly. Fix #41525 Fix #42754
1 parent 957fdb9 commit 118eee9

16 files changed

Lines changed: 124 additions & 97 deletions

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ClassDataContract.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ internal static bool IsNonAttributedTypeValidForSerialization(Type type)
388388
else
389389
{
390390
return (type.IsVisible &&
391-
type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, Array.Empty<Type>()) != null);
391+
type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Array.Empty<Type>(), null) != null);
392392
}
393393
}
394394

@@ -1368,7 +1368,7 @@ private void SetKeyValuePairAdapterFlags(Type type)
13681368
{
13691369
_isKeyValuePairAdapter = true;
13701370
_keyValuePairGenericArguments = type.GetGenericArguments();
1371-
_keyValuePairCtorInfo = type.GetConstructor(Globals.ScanAllMembers, new Type[] { Globals.TypeOfKeyValuePair.MakeGenericType(_keyValuePairGenericArguments) });
1371+
_keyValuePairCtorInfo = type.GetConstructor(Globals.ScanAllMembers, null, new Type[] { Globals.TypeOfKeyValuePair.MakeGenericType(_keyValuePairGenericArguments) }, null);
13721372
_getKeyValuePairMethodInfo = type.GetMethod("GetKeyValuePair", Globals.ScanAllMembers)!;
13731373
}
13741374
}
@@ -1425,7 +1425,7 @@ internal MethodInfo? GetKeyValuePairMethodInfo
14251425
if (type.IsValueType)
14261426
return null;
14271427

1428-
ConstructorInfo? ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, Array.Empty<Type>());
1428+
ConstructorInfo? ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Array.Empty<Type>(), null);
14291429
if (ctor == null)
14301430
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.NonAttributedSerializableTypesMustHaveDefaultConstructor, DataContract.GetClrTypeFullName(type))));
14311431

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/CodeGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ private static MethodInfo ObjectEquals
3838
{
3939
if (s_objectEquals == null)
4040
{
41-
s_objectEquals = Globals.TypeOfObject.GetMethod("Equals", BindingFlags.Public | BindingFlags.Static);
41+
s_objectEquals = typeof(object).GetMethod("Equals", BindingFlags.Public | BindingFlags.Static);
4242
Debug.Assert(s_objectEquals != null);
4343
}
4444
return s_objectEquals;

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/CollectionDataContract.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ internal Type GetCollectionElementType()
883883
enumeratorType = GetEnumeratorMethod.ReturnType;
884884
}
885885

886-
MethodInfo? getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, Array.Empty<Type>());
886+
MethodInfo? getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null);
887887
if (getCurrentMethod == null)
888888
{
889889
if (enumeratorType.IsInterface)
@@ -1134,7 +1134,7 @@ private static bool IsCollectionOrTryCreate(Type type, bool tryCreate, out DataC
11341134
}
11351135
}
11361136

1137-
getEnumeratorMethod = Globals.TypeOfIEnumerable.GetMethod(Globals.GetEnumeratorMethodName)!;
1137+
getEnumeratorMethod = typeof(IEnumerable).GetMethod(Globals.GetEnumeratorMethodName)!;
11381138
}
11391139
if (tryCreate)
11401140
dataContract = new CollectionDataContract(type, (CollectionKind)(i + 1), itemType, getEnumeratorMethod, addMethod, null/*defaultCtor*/);
@@ -1364,7 +1364,7 @@ private static void GetCollectionMethods(Type type, Type interfaceType, Type[] a
13641364

13651365
if (getEnumeratorMethod == null)
13661366
{
1367-
getEnumeratorMethod = type.GetMethod(Globals.GetEnumeratorMethodName, BindingFlags.Instance | BindingFlags.Public, Array.Empty<Type>());
1367+
getEnumeratorMethod = type.GetMethod(Globals.GetEnumeratorMethodName, BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null);
13681368
if (getEnumeratorMethod == null || !Globals.TypeOfIEnumerator.IsAssignableFrom(getEnumeratorMethod.ReturnType))
13691369
{
13701370
Type? ienumerableInterface = interfaceType.GetInterfaces().Where(t => t.FullName!.StartsWith("System.Collections.Generic.IEnumerable")).FirstOrDefault();

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DataContract.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,7 @@ internal MethodInfo? ParseMethod
11251125
{
11261126
if (!_parseMethodSet)
11271127
{
1128-
MethodInfo? method = UnderlyingType.GetMethod(Globals.ParseMethodName, BindingFlags.Public | BindingFlags.Static, new Type[] { typeof(string) });
1128+
MethodInfo? method = UnderlyingType.GetMethod(Globals.ParseMethodName, BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string) }, null);
11291129

11301130
if (method != null && method.ReturnType == UnderlyingType)
11311131
{
@@ -1978,7 +1978,7 @@ private static void ImportKnownTypeAttributes(Type? type, Dictionary<Type, Type>
19781978
if (methodName.Length == 0)
19791979
DataContract.ThrowInvalidDataContractException(SR.Format(SR.KnownTypeAttributeEmptyString, DataContract.GetClrTypeFullName(type)), type);
19801980

1981-
MethodInfo? method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, Array.Empty<Type>());
1981+
MethodInfo? method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, Array.Empty<Type>(), null);
19821982
if (method == null)
19831983
DataContract.ThrowInvalidDataContractException(SR.Format(SR.KnownTypeAttributeUnknownMethod, methodName, DataContract.GetClrTypeFullName(type)), type);
19841984

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Globals.cs

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -785,46 +785,6 @@ internal static Uri DataContractXsdBaseNamespaceUri
785785
}
786786
}
787787

788-
#region Contract compliance for System.Type
789-
790-
private static bool TypeSequenceEqual(Type[] seq1, Type[] seq2)
791-
{
792-
if (seq1 == null || seq2 == null || seq1.Length != seq2.Length)
793-
return false;
794-
for (int i = 0; i < seq1.Length; i++)
795-
{
796-
if (!seq1[i].Equals(seq2[i]) && !seq1[i].IsAssignableFrom(seq2[i]))
797-
return false;
798-
}
799-
return true;
800-
}
801-
802-
private static MethodBase? FilterMethodBases(MethodBase[]? methodBases, Type[] parameterTypes, string methodName)
803-
{
804-
if (methodBases == null || string.IsNullOrEmpty(methodName))
805-
return null;
806-
807-
var matchedMethods = methodBases.Where(method => method.Name.Equals(methodName));
808-
matchedMethods = matchedMethods.Where(method => TypeSequenceEqual(method.GetParameters().Select(param => param.ParameterType).ToArray(), parameterTypes));
809-
return matchedMethods.FirstOrDefault();
810-
}
811-
812-
internal static ConstructorInfo? GetConstructor(this Type type, BindingFlags bindingFlags, Type[] parameterTypes)
813-
{
814-
ConstructorInfo[] constructorInfos = type.GetConstructors(bindingFlags);
815-
var constructorInfo = FilterMethodBases(constructorInfos.Cast<MethodBase>().ToArray()!, parameterTypes, ".ctor");
816-
return constructorInfo != null ? (ConstructorInfo)constructorInfo : null;
817-
}
818-
819-
internal static MethodInfo? GetMethod(this Type type, string methodName, BindingFlags bindingFlags, Type[] parameterTypes)
820-
{
821-
var methodInfos = type.GetMethods(bindingFlags);
822-
var methodInfo = FilterMethodBases(methodInfos.Cast<MethodBase>().ToArray()!, parameterTypes, methodName);
823-
return methodInfo != null ? (MethodInfo)methodInfo : null;
824-
}
825-
826-
#endregion
827-
828788
private static readonly Type? s_typeOfScriptObject;
829789

830790
internal static ClassDataContract CreateScriptObjectClassDataContract()

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatGeneratorStatics.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ public static MethodInfo GetUninitializedObjectMethod
167167
{
168168
if (s_getUninitializedObjectMethod == null)
169169
{
170-
s_getUninitializedObjectMethod = typeof(XmlFormatReaderGenerator).GetMethod("UnsafeGetUninitializedObject", Globals.ScanAllMembers, new Type[] { typeof(Type) });
170+
s_getUninitializedObjectMethod = typeof(XmlFormatReaderGenerator).GetMethod("UnsafeGetUninitializedObject", Globals.ScanAllMembers, null, new Type[] { typeof(Type) }, null);
171171
Debug.Assert(s_getUninitializedObjectMethod != null);
172172
}
173173
return s_getUninitializedObjectMethod;
@@ -180,7 +180,7 @@ public static MethodInfo IsStartElementMethod0
180180
{
181181
if (s_isStartElementMethod0 == null)
182182
{
183-
s_isStartElementMethod0 = typeof(XmlReaderDelegator).GetMethod("IsStartElement", Globals.ScanAllMembers, Array.Empty<Type>());
183+
s_isStartElementMethod0 = typeof(XmlReaderDelegator).GetMethod("IsStartElement", Globals.ScanAllMembers, null, Array.Empty<Type>(), null);
184184
Debug.Assert(s_isStartElementMethod0 != null);
185185
}
186186
return s_isStartElementMethod0;
@@ -192,7 +192,7 @@ public static MethodInfo IsStartElementMethod2
192192
{
193193
if (s_isStartElementMethod2 == null)
194194
{
195-
s_isStartElementMethod2 = typeof(XmlReaderDelegator).GetMethod("IsStartElement", Globals.ScanAllMembers, new Type[] { typeof(XmlDictionaryString), typeof(XmlDictionaryString) });
195+
s_isStartElementMethod2 = typeof(XmlReaderDelegator).GetMethod("IsStartElement", Globals.ScanAllMembers, null, new Type[] { typeof(XmlDictionaryString), typeof(XmlDictionaryString) }, null);
196196
Debug.Assert(s_isStartElementMethod2 != null);
197197
}
198198
return s_isStartElementMethod2;
@@ -371,7 +371,7 @@ public static MethodInfo WriteAttributeStringMethod
371371
{
372372
if (s_writeAttributeStringMethod == null)
373373
{
374-
s_writeAttributeStringMethod = typeof(XmlWriterDelegator).GetMethod("WriteAttributeString", Globals.ScanAllMembers, new Type[] { typeof(string), typeof(string), typeof(string), typeof(string) });
374+
s_writeAttributeStringMethod = typeof(XmlWriterDelegator).GetMethod("WriteAttributeString", Globals.ScanAllMembers, null, new Type[] { typeof(string), typeof(string), typeof(string), typeof(string) }, null);
375375
Debug.Assert(s_writeAttributeStringMethod != null);
376376
}
377377
return s_writeAttributeStringMethod;
@@ -383,7 +383,7 @@ public static MethodInfo WriteEndElementMethod
383383
{
384384
if (s_writeEndElementMethod == null)
385385
{
386-
s_writeEndElementMethod = typeof(XmlWriterDelegator).GetMethod("WriteEndElement", Globals.ScanAllMembers, Array.Empty<Type>());
386+
s_writeEndElementMethod = typeof(XmlWriterDelegator).GetMethod("WriteEndElement", Globals.ScanAllMembers, null, Array.Empty<Type>(), null);
387387
Debug.Assert(s_writeEndElementMethod != null);
388388
}
389389
return s_writeEndElementMethod;
@@ -431,7 +431,7 @@ public static MethodInfo WriteStartElementMethod
431431
{
432432
if (s_writeStartElementMethod == null)
433433
{
434-
s_writeStartElementMethod = typeof(XmlWriterDelegator).GetMethod("WriteStartElement", Globals.ScanAllMembers, new Type[] { typeof(XmlDictionaryString), typeof(XmlDictionaryString) });
434+
s_writeStartElementMethod = typeof(XmlWriterDelegator).GetMethod("WriteStartElement", Globals.ScanAllMembers, null, new Type[] { typeof(XmlDictionaryString), typeof(XmlDictionaryString) }, null);
435435
Debug.Assert(s_writeStartElementMethod != null);
436436
}
437437
return s_writeStartElementMethod;
@@ -444,7 +444,7 @@ public static MethodInfo WriteStartElementStringMethod
444444
{
445445
if (s_writeStartElementStringMethod == null)
446446
{
447-
s_writeStartElementStringMethod = typeof(XmlWriterDelegator).GetMethod("WriteStartElement", Globals.ScanAllMembers, new Type[] { typeof(string), typeof(string) });
447+
s_writeStartElementStringMethod = typeof(XmlWriterDelegator).GetMethod("WriteStartElement", Globals.ScanAllMembers, null, new Type[] { typeof(string), typeof(string) }, null);
448448
Debug.Assert(s_writeStartElementStringMethod != null);
449449
}
450450
return s_writeStartElementStringMethod;
@@ -457,7 +457,7 @@ public static MethodInfo ParseEnumMethod
457457
{
458458
if (s_parseEnumMethod == null)
459459
{
460-
s_parseEnumMethod = typeof(Enum).GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, new Type[] { typeof(Type), typeof(string) });
460+
s_parseEnumMethod = typeof(Enum).GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(Type), typeof(string) }, null);
461461
Debug.Assert(s_parseEnumMethod != null);
462462
}
463463
return s_parseEnumMethod;
@@ -470,7 +470,7 @@ public static MethodInfo GetJsonMemberNameMethod
470470
{
471471
if (s_getJsonMemberNameMethod == null)
472472
{
473-
s_getJsonMemberNameMethod = typeof(XmlObjectSerializerReadContextComplexJson).GetMethod("GetJsonMemberName", Globals.ScanAllMembers, new Type[] { typeof(XmlReaderDelegator) });
473+
s_getJsonMemberNameMethod = typeof(XmlObjectSerializerReadContextComplexJson).GetMethod("GetJsonMemberName", Globals.ScanAllMembers, null, new Type[] { typeof(XmlReaderDelegator) }, null);
474474
Debug.Assert(s_getJsonMemberNameMethod != null);
475475
}
476476
return s_getJsonMemberNameMethod;

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatReaderGenerator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -573,11 +573,11 @@ private void ReadCollection(CollectionDataContract collectionContract)
573573
{
574574
case CollectionKind.GenericDictionary:
575575
type = Globals.TypeOfDictionaryGeneric.MakeGenericType(itemType.GetGenericArguments());
576-
constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Array.Empty<Type>())!;
576+
constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Array.Empty<Type>(), null)!;
577577
break;
578578
case CollectionKind.Dictionary:
579579
type = Globals.TypeOfHashtable;
580-
constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Array.Empty<Type>())!;
580+
constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Array.Empty<Type>(), null)!;
581581
break;
582582
case CollectionKind.Collection:
583583
case CollectionKind.GenericCollection:

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatWriterGenerator.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,8 @@ private void WriteCollection(CollectionDataContract collectionContract)
346346
{
347347
enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType;
348348
}
349-
MethodInfo? moveNextMethod = enumeratorType.GetMethod(Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, Array.Empty<Type>());
350-
MethodInfo? getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, Array.Empty<Type>());
349+
MethodInfo? moveNextMethod = enumeratorType.GetMethod(Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null);
350+
MethodInfo? getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null);
351351
if (moveNextMethod == null || getCurrentMethod == null)
352352
{
353353
if (enumeratorType.IsInterface)
@@ -388,15 +388,15 @@ private void WriteCollection(CollectionDataContract collectionContract)
388388
_ilg.Call(_objectLocal, collectionContract.GetEnumeratorMethod);
389389
if (isDictionary)
390390
{
391-
ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, new Type[] { Globals.TypeOfIDictionaryEnumerator })!;
391+
ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { Globals.TypeOfIDictionaryEnumerator }, null)!;
392392
_ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, Globals.TypeOfIDictionaryEnumerator);
393393
_ilg.New(dictEnumCtor);
394394
}
395395
else if (isGenericDictionary)
396396
{
397397
Debug.Assert(keyValueTypes != null);
398398
Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes));
399-
ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, new Type[] { ctorParam })!;
399+
ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { ctorParam }, null)!;
400400
_ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, ctorParam);
401401
_ilg.New(dictEnumCtor);
402402
}
@@ -560,7 +560,9 @@ private bool TryWritePrimitiveArray(Type type, Type itemType, LocalBuilder value
560560
MethodInfo writeArrayMethodInfo = typeof(JsonWriterDelegator).GetMethod(
561561
writeArrayMethod,
562562
Globals.ScanAllMembers,
563-
new Type[] { type, typeof(XmlDictionaryString), typeof(XmlDictionaryString) })!;
563+
null,
564+
new Type[] { type, typeof(XmlDictionaryString), typeof(XmlDictionaryString) },
565+
null)!;
564566
_ilg.Call(_xmlWriterArg, writeArrayMethodInfo, value, itemName, null);
565567
return true;
566568
}

0 commit comments

Comments
 (0)