Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 00ec7f6

Browse files
committed
Fix XmlSerializer issue when deserializing type with protected parameterless constructor
1 parent d98e0a4 commit 00ec7f6

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

src/System.Xml.XmlSerializer/src/System/Xml/Serialization/XmlSerializationWriterILGen.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2416,6 +2416,67 @@ internal void ILGenForCreateInstance(CodeGenerator ilg, Type type, Type cast, bo
24162416
}
24172417
}
24182418

2419+
Label labelReturn = ilg.DefineLabel();
2420+
Label labelEndIf = ilg.DefineLabel();
2421+
2422+
// Type typeInfo = type.GetTypeInfo();
2423+
LocalBuilder typeInfo = ilg.DeclareLocal(typeof(TypeInfo), "typeInfo");
2424+
ilg.Ldc(type);
2425+
MethodInfo getTypeInfoMehod = typeof(IntrospectionExtensions).GetMethod(
2426+
"GetTypeInfo",
2427+
CodeGenerator.StaticBindingFlags,
2428+
new[] { typeof(Type) }
2429+
);
2430+
ilg.Call(getTypeInfoMehod);
2431+
2432+
// IEnumerator e = typeInfo.DeclaredConstructors.GetEnumerator();
2433+
LocalBuilder enumerator = ilg.DeclareLocal(typeof(IEnumerator), "e");
2434+
MethodInfo getDeclaredConstructors = typeof(TypeInfo).GetMethod("get_DeclaredConstructors");
2435+
MethodInfo getEnumerator =
2436+
typeof(IEnumerable<>).MakeGenericType(typeof(ConstructorInfo)).GetMethod("GetEnumerator");
2437+
ilg.Call(getDeclaredConstructors);
2438+
ilg.Call(getEnumerator);
2439+
ilg.Stloc(enumerator);
2440+
2441+
ilg.WhileBegin();
2442+
// ConstructorInfo constructorInfo = e.Current();
2443+
MethodInfo enumeratorCurrent = typeof(IEnumerator).GetMethod("get_Current");
2444+
ilg.Ldloc(enumerator);
2445+
ilg.Call(enumeratorCurrent);
2446+
LocalBuilder constructorInfo = ilg.DeclareLocal(typeof(ConstructorInfo), "constructorInfo");
2447+
ilg.Stloc(constructorInfo);
2448+
2449+
// if (!constructorInfo.IsStatic || constructorInfo.GetParameters.Length() == 0)
2450+
ilg.Ldloc(constructorInfo);
2451+
MethodInfo constructorIsStatic = typeof(ConstructorInfo).GetMethod("get_IsStatic");
2452+
ilg.Call(constructorIsStatic);
2453+
ilg.Brtrue(labelEndIf);
2454+
ilg.Ldloc(constructorInfo);
2455+
MethodInfo constructorGetParameters = typeof(ConstructorInfo).GetMethod("GetParameters");
2456+
ilg.Call(constructorGetParameters);
2457+
ilg.Ldlen();
2458+
ilg.Ldc(0);
2459+
ilg.Cne();
2460+
ilg.Brtrue(labelEndIf);
2461+
2462+
// constructorInfo.Invoke(null);
2463+
MethodInfo constructorInvoke = typeof(ConstructorInfo).GetMethod("Invoke", new Type[] { typeof(object[]) });
2464+
ilg.Ldloc(constructorInfo);
2465+
ilg.Load(null);
2466+
ilg.Call(constructorInvoke);
2467+
ilg.Br(labelReturn);
2468+
2469+
ilg.MarkLabel(labelEndIf);
2470+
ilg.WhileBeginCondition(); // while (e.MoveNext())
2471+
MethodInfo IEnumeratorMoveNext = typeof(IEnumerator).GetMethod(
2472+
"MoveNext",
2473+
CodeGenerator.InstanceBindingFlags,
2474+
Array.Empty<Type>());
2475+
ilg.Ldloc(enumerator);
2476+
ilg.Call(IEnumeratorMoveNext);
2477+
ilg.WhileEndCondition();
2478+
ilg.WhileEnd();
2479+
24192480
MethodInfo Activator_CreateInstance = typeof(Activator).GetMethod(
24202481
"CreateInstance",
24212482
CodeGenerator.StaticBindingFlags,
@@ -2425,6 +2486,7 @@ internal void ILGenForCreateInstance(CodeGenerator ilg, Type type, Type cast, bo
24252486
ilg.Call(Activator_CreateInstance);
24262487
if (cast != null)
24272488
ilg.ConvertValue(Activator_CreateInstance.ReturnType, cast);
2489+
ilg.MarkLabel(labelReturn);
24282490
}
24292491

24302492
internal void WriteLocalDecl(string variableName, SourceInfo initValue)

src/System.Xml.XmlSerializer/tests/XmlSerializerTests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,17 @@ public static void Xml_TypeWithMismatchBetweenAttributeAndPropertyType()
11111111
Assert.StrictEqual(value.IntValue, actual.IntValue);
11121112
}
11131113

1114+
[Fact]
1115+
public static void Xml_TypeWithNonPublicDefaultConstructor()
1116+
{
1117+
System.Reflection.TypeInfo ti = System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(TypeWithNonPublicDefaultConstructor));
1118+
TypeWithNonPublicDefaultConstructor value = null;
1119+
value = (TypeWithNonPublicDefaultConstructor)FindDefaultConstructor(ti).Invoke(null);
1120+
Assert.StrictEqual("Mr. FooName", value.Name);
1121+
var actual = SerializeAndDeserialize<TypeWithNonPublicDefaultConstructor>(value, "<?xml version=\"1.0\"?>\r\n<TypeWithNonPublicDefaultConstructor xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <Name>Mr. FooName</Name>\r\n</TypeWithNonPublicDefaultConstructor>");
1122+
Assert.StrictEqual(value.Name, actual.Name);
1123+
}
1124+
11141125
private static T SerializeAndDeserialize<T>(T value, string baseline, Func<XmlSerializer> serializerFactory = null)
11151126
{
11161127
XmlSerializer serializer = new XmlSerializer(typeof(T));

0 commit comments

Comments
 (0)