Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions YAXLib/ReflectionUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -676,10 +676,24 @@ public static object ConvertBasicType(object value, Type dstType)
/// <summary>
/// Searches all loaded assemblies to find a type with a special name.
/// </summary>
/// <param name="name">The name of the type to find.</param>
/// <remarks>
/// Types from System.Private.CoreLib (NETSTANDARD, NET5.0) the corresponding type from mscorlib (NETFRAMEWORK)
/// will be returned and vice versa, depending on the framework the executing assembly is compiled for.
/// </remarks>
/// <param name="name">The <see cref="Type.AssemblyQualifiedName"/> of the type to find.</param>
/// <returns><see cref="Type"/> found using the specified name</returns>
public static Type GetTypeByName(string name)
{
var pattern =
System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework")
// Forward compatibility:
// if we get a yaxlib:realtype which is NETSTANDARD or NET5.0 System.Private.CoreLib, replace it with its equivalent
? @"\,\s+(System\.Private\.CoreLib)\,\s+Version\=\d+(\.\d+)*\,\s+Culture=\b\w+\b\,\s+PublicKeyToken\=\b\w+\b"
// Backward compatibility:
// if we get a yaxlib:realtype which is .Net Framework 2.x/3.x/4.x mscorlib, replace it with its equivalent
: @"\,\s+(mscorlib)\,\s+Version\=\d+(\.\d+)*\,\s+Culture=\b\w+\b\,\s+PublicKeyToken\=\b\w+\b";
var execAppFxName = System.Text.RegularExpressions.Regex.Replace(name, pattern, name.GetType().Assembly.FullName);

var assemblies = AppDomain.CurrentDomain.GetAssemblies();

// first search the 1st assembly (i.e. the mscorlib), then start from the last assembly backward,
Expand All @@ -690,12 +704,13 @@ public static Type GetTypeByName(string name)

try
{
var type = curAssembly.GetType(name, false, true);
var type = curAssembly.GetType(execAppFxName, false, true);
if (type != null)
return type;
}
catch
{
// ignored
}
}

Expand Down
19 changes: 12 additions & 7 deletions YAXLibTests/ReflectionUtilsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,24 @@ public void EqualsOrIsNullableOfTest()
Assert.That(typeof(int[]).EqualsOrIsNullableOf(typeof(Array)), Is.False);
}

[Test]
public void GetTypeByNameTest()
#if NETFRAMEWORK
[TestCase("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] // NETFRAMEWORK2.x
[TestCase("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] // NETFRAMEWORK4.x
#elif NETCOREAPP3_1
[TestCase("System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e")] // NETSTANDARD
#else
[TestCase("System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e")] // NETSTANDARD
[TestCase("System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e")] // NET5.0
#endif
public void GetTypeByNameTest(string coreLibName)
{
var type1 = ReflectionUtils.GetTypeByName(
"System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]");
$"System.Collections.Generic.List`1[[System.Int32, {coreLibName}]]");
var type2 = ReflectionUtils.GetTypeByName("System.Collections.Generic.List`1[[System.Int32]]");
var type3 = ReflectionUtils.GetTypeByName(
"System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral]]");

Assert.That(type1, Is.Not.Null);
Assert.That(type2, Is.Not.Null);
Assert.That(type3, Is.Not.Null);
Assert.That(type2, Is.EqualTo(type1));
Assert.That(type3, Is.EqualTo(type2));
}
}
}
2 changes: 1 addition & 1 deletion YAXLibTests/SampleClasses/GUIDTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace YAXLibTests.SampleClasses
{
[ShowInDemoApplication]
[YAXComment("This example shows serialization and deserialization of GUID obejcts")]
[YAXComment("This example shows serialization and deserialization of GUID objects")]
public class GUIDTest
{
public Guid StandaloneGuid { get; set; }
Expand Down
99 changes: 25 additions & 74 deletions YAXLibTests/SerializationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -430,51 +430,15 @@ public void PathsExampleTest()
var got = serializer.Serialize(PathsExample.GetSampleInstance());
Assert.That(got, Is.EqualTo(result));
}

[Test]
public void MoreComplexExampleTest()

[TestCase("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] // NETFRAMEWORK2.x
[TestCase("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] // NETFRAMEWORK4.x
[TestCase("System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e")] // NETSTANDARD
[TestCase("System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e")] // NET5.0
public void MoreComplexExample_CrossFramework_Test(string coreLibName)
{
#if NETCOREAPP3_1 || NET5_0
const string result =
@"<!-- This example tries to show almost all features of YAXLib which were not shown before. -->
<!-- FamousPoints - shows a dictionary with a non-primitive value member. -->
<!-- IntEnumerable - shows serializing properties of type IEnumerable<> -->
<!-- Students - shows the usage of YAXNotCollection attribute -->
<MoreComplexExample xmlns:yaxlib=""http://www.sinairv.com/yaxlib/"">
<FamousPoints>
<PointInfo PName=""Center"">
<ThePoint X=""0"" Y=""0"" />
</PointInfo>
<PointInfo PName=""Q1"">
<ThePoint X=""1"" Y=""1"" />
</PointInfo>
<PointInfo PName=""Q2"">
<ThePoint X=""-1"" Y=""1"" />
</PointInfo>
</FamousPoints>
<IntEnumerable yaxlib:realtype=""System.Collections.Generic.List`1[[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]"">
<Int32>1</Int32>
<Int32>3</Int32>
<Int32>5</Int32>
<Int32>7</Int32>
</IntEnumerable>
<Students>
<Count>3</Count>
<Names>
<String>Ali</String>
<String>Dave</String>
<String>John</String>
</Names>
<Families>
<String>Alavi</String>
<String>Black</String>
<String>Doe</String>
</Families>
</Students>
</MoreComplexExample>";
#else
const string result =
@"<!-- This example tries to show almost all features of YAXLib which were not shown before. -->
var result =
$@"<!-- This example tries to show almost all features of YAXLib which were not shown before. -->
<!-- FamousPoints - shows a dictionary with a non-primitive value member. -->
<!-- IntEnumerable - shows serializing properties of type IEnumerable<> -->
<!-- Students - shows the usage of YAXNotCollection attribute -->
Expand All @@ -490,7 +454,7 @@ public void MoreComplexExampleTest()
<ThePoint X=""-1"" Y=""1"" />
</PointInfo>
</FamousPoints>
<IntEnumerable yaxlib:realtype=""System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"">
<IntEnumerable yaxlib:realtype=""System.Collections.Generic.List`1[[System.Int32, {coreLibName}]]"">
<Int32>1</Int32>
<Int32>3</Int32>
<Int32>5</Int32>
Expand All @@ -510,7 +474,6 @@ public void MoreComplexExampleTest()
</Families>
</Students>
</MoreComplexExample>";
#endif
var serializer = new YAXSerializer(typeof(MoreComplexExample), YAXExceptionHandlingPolicies.DoNotThrow,
YAXExceptionTypes.Warning, YAXSerializationOptions.SerializeNullObjects);
var got = serializer.Serialize(MoreComplexExample.GetSampleInstance());
Expand Down Expand Up @@ -618,7 +581,7 @@ public void GuidDemoTest()
var g4 = Guid.NewGuid();

var result = string.Format(
@"<!-- This example shows serialization and deserialization of GUID obejcts -->
@"<!-- This example shows serialization and deserialization of GUID objects -->
<GUIDTest>
<StandaloneGuid>{3}</StandaloneGuid>
<SomeDic>
Expand Down Expand Up @@ -1682,56 +1645,44 @@ public void PolymorphicSerializationThroughObjectTest()
Assert.That(desObj.ToString(), Is.EqualTo(content.ToString()));
}

[Test]
public void PolymorphicSerializationThroughListTest()
[TestCase("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] // NETFRAMEWORK2.x
[TestCase("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] // NETFRAMEWORK4.x
[TestCase("System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e")] // NETSTANDARD
[TestCase("System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e")] // NET5.0
public void PolymorphicSerializationThroughList_CrossFramework_Test(string coreLibName)
{
var lst = new List<int> {1, 2, 3};
var ser = new YAXSerializer(typeof(object));
var xmlResult = ser.Serialize(lst);
#if NETCOREAPP3_1 || NET5_0
const string expectedResult =
@"<Object yaxlib:realtype=""System.Collections.Generic.List`1[[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]"" xmlns:yaxlib=""http://www.sinairv.com/yaxlib/"">
<Int32>1</Int32>
<Int32>2</Int32>
<Int32>3</Int32>
</Object>";
#else
const string expectedResult =
@"<Object yaxlib:realtype=""System.Collections.Generic.List`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"" xmlns:yaxlib=""http://www.sinairv.com/yaxlib/"">
var expectedResult =
$@"<Object yaxlib:realtype=""System.Collections.Generic.List`1[[System.Int32, {coreLibName}]]"" xmlns:yaxlib=""http://www.sinairv.com/yaxlib/"">
<Int32>1</Int32>
<Int32>2</Int32>
<Int32>3</Int32>
</Object>";
#endif
Assert.That(xmlResult.StripTypeAssemblyVersion(), Is.EqualTo(expectedResult.StripTypeAssemblyVersion()));
var desObj = ser.Deserialize(xmlResult);
Assert.That(desObj.GetType(), Is.EqualTo(lst.GetType()));
var desLst = desObj as List<int>;
Assert.That(lst, Has.Count.EqualTo(desLst.Count));
Assert.That(lst, Is.EquivalentTo(desLst));
}

[Test]
public void PolymorphicSerializationThroughListWhichMayContainYaxlibNamespaceTest()

[TestCase("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] // NETFRAMEWORK2.x
[TestCase("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] // NETFRAMEWORK4.x
[TestCase("System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e")] // NETSTANDARD
[TestCase("System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e")] // NET5.0
public void PolymorphicSerializationThroughListWhichMayContainYaxlibNamespace_CrossFramework_Test(string coreLibName)
{
var lst = new List<object> {1, 2, 3};
var ser = new YAXSerializer(typeof(object));
var xmlResult = ser.Serialize(lst);
#if NETCOREAPP3_1 || NET5_0
const string expectedResult =
@"<Object xmlns:yaxlib=""http://www.sinairv.com/yaxlib/"" yaxlib:realtype=""System.Collections.Generic.List`1[[System.Object, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]"">
<Object yaxlib:realtype=""System.Int32"">1</Object>
<Object yaxlib:realtype=""System.Int32"">2</Object>
<Object yaxlib:realtype=""System.Int32"">3</Object>
</Object>";
#else
const string expectedResult =
@"<Object xmlns:yaxlib=""http://www.sinairv.com/yaxlib/"" yaxlib:realtype=""System.Collections.Generic.List`1[[System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"">
var expectedResult =
$@"<Object xmlns:yaxlib=""http://www.sinairv.com/yaxlib/"" yaxlib:realtype=""System.Collections.Generic.List`1[[System.Object, {coreLibName}]]"">
<Object yaxlib:realtype=""System.Int32"">1</Object>
<Object yaxlib:realtype=""System.Int32"">2</Object>
<Object yaxlib:realtype=""System.Int32"">3</Object>
</Object>";
#endif
Assert.That(xmlResult.StripTypeAssemblyVersion(), Is.EqualTo(expectedResult.StripTypeAssemblyVersion()));
var desObj = ser.Deserialize(xmlResult);
Assert.That(desObj.GetType(), Is.EqualTo(lst.GetType()));
Expand Down
2 changes: 1 addition & 1 deletion YAXLibTests/StringExtensionsForTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public static class StringExtensionsForTest
{
public static string StripTypeAssemblyVersion(this string str)
{
const string pattern = @"\,\s+Version\=\d+(\.\d+)*\,\s+Culture=\b\w+\b\,\s+PublicKeyToken\=\b\w+\b";
const string pattern = @"\,\s+(mscorlib|System\.Private\.CoreLib)\,\s+Version\=\d+(\.\d+)*\,\s+Culture=\b\w+\b\,\s+PublicKeyToken\=\b\w+\b";
return Regex.Replace(str, pattern, string.Empty);
}
}
Expand Down