From a06a764f74e349d7b909e74d0a3d2e965f50d165 Mon Sep 17 00:00:00 2001
From: "dependabot-preview[bot]"
<27856297+dependabot-preview[bot]@users.noreply.github.com>
Date: Fri, 27 Dec 2019 16:57:36 +0000
Subject: [PATCH 1/8] Bump System.Collections.Immutable from 1.6.0 to 1.7.0
(#148)
---
src/Hyperion.Tests/Hyperion.Tests.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Hyperion.Tests/Hyperion.Tests.csproj b/src/Hyperion.Tests/Hyperion.Tests.csproj
index 8bebdc43..782667db 100644
--- a/src/Hyperion.Tests/Hyperion.Tests.csproj
+++ b/src/Hyperion.Tests/Hyperion.Tests.csproj
@@ -11,7 +11,7 @@
-
+
From d0f963a11114a36e87e303e685871ae2bf6f8d84 Mon Sep 17 00:00:00 2001
From: "dependabot-preview[bot]"
<27856297+dependabot-preview[bot]@users.noreply.github.com>
Date: Fri, 27 Dec 2019 17:52:32 +0000
Subject: [PATCH 2/8] Bump System.Reflection.TypeExtensions from 4.6.0 to 4.7.0
(#147)
---
src/Hyperion/Hyperion.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Hyperion/Hyperion.csproj b/src/Hyperion/Hyperion.csproj
index ea82a236..99ebc54c 100644
--- a/src/Hyperion/Hyperion.csproj
+++ b/src/Hyperion/Hyperion.csproj
@@ -10,7 +10,7 @@
-
+
From 54e13f06491efbeffd7560e346dda507a0d99677 Mon Sep 17 00:00:00 2001
From: "dependabot-preview[bot]"
<27856297+dependabot-preview[bot]@users.noreply.github.com>
Date: Mon, 13 Jan 2020 21:14:36 +0000
Subject: [PATCH 3/8] Bump Microsoft.CSharp from 4.6.0 to 4.7.0 (#146)
---
src/Hyperion/Hyperion.csproj | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Hyperion/Hyperion.csproj b/src/Hyperion/Hyperion.csproj
index 99ebc54c..3da7b049 100644
--- a/src/Hyperion/Hyperion.csproj
+++ b/src/Hyperion/Hyperion.csproj
@@ -11,12 +11,12 @@
-
+
-
+
From 3d65b93b8d879b7619de6fc4b68c1aaee44ca3b3 Mon Sep 17 00:00:00 2001
From: Igor Fedchenko
Date: Fri, 17 Jan 2020 02:47:16 +0300
Subject: [PATCH 4/8] Fix version tolerance when bad assembly version specified
in type manifest (#149)
* Added red test
* Ignore assembly version, if specified
* Handling assembly loading failure
* Fix mscorelib substitution case
* Fixed ToQualifiedAssemblyName test
* Strip assembly version with regex
* Reuse existing assembly version strip regex
---
src/Hyperion.Tests/Bugs.cs | 68 +++++++++++++++++++
src/Hyperion.Tests/Hyperion.Tests.csproj | 1 +
src/Hyperion/Extensions/TypeEx.cs | 28 +++++++-
src/Hyperion/Hyperion.csproj | 5 ++
.../ValueSerializers/TypeSerializer.cs | 3 +-
5 files changed, 100 insertions(+), 5 deletions(-)
diff --git a/src/Hyperion.Tests/Bugs.cs b/src/Hyperion.Tests/Bugs.cs
index 1be64854..a4ebe36c 100644
--- a/src/Hyperion.Tests/Bugs.cs
+++ b/src/Hyperion.Tests/Bugs.cs
@@ -11,6 +11,11 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
+using FluentAssertions;
+using Hyperion.Extensions;
using Xunit;
namespace Hyperion.Tests
@@ -85,6 +90,69 @@ public void CanSerializeMessageWithByte()
var res = serializer.Deserialize(stream);
}
+ ///
+ /// Fix for https://github.com/akkadotnet/Hyperion/issues/144
+ ///
+ [Fact]
+ public void CanFindTypeByManifest_WhenManifestContainsUnknownAssemblyVersion()
+ {
+ var serializer = new Serializer(new SerializerOptions(versionTolerance: true, preserveObjectReferences: true));
+ var type = typeof(ByteMessage);
+
+ MemoryStream GetStreamForManifest(string manifest)
+ {
+ var stream = new MemoryStream();
+ stream.WriteLengthEncodedByteArray(manifest.ToUtf8Bytes(), serializer.GetSerializerSession());
+ stream.Position = 0;
+ return stream;
+ }
+
+ // This is used in serialized manifest, should be something like 'Hyperion.Tests.Bugs+ByteMessage, Hyperion.Tests'
+ var shortName = type.GetShortAssemblyQualifiedName();
+ var shortNameStream = GetStreamForManifest(shortName);
+ // Something like 'Hyperion.Tests.Bugs+ByteMessage, Hyperion.Tests, Version=0.9.11.0, Culture=neutral, PublicKeyToken=null'
+ var fullName = type.AssemblyQualifiedName;
+ var fullNameStream = GetStreamForManifest(fullName);
+ // Set bad assembly version to make deserialization fail
+ var fullNameWithUnknownVersion = fullName.Remove(fullName.IndexOf(", Version=")) + ", Version=999999, Culture=neutral, PublicKeyToken=null";
+ var fullNameWithUnknownVersionStream = GetStreamForManifest(fullNameWithUnknownVersion);
+
+ this.Invoking(_ => TypeEx.GetTypeFromManifestFull(shortNameStream, serializer.GetDeserializerSession()))
+ .Should().NotThrow("When assembly short name is specified in manifest, should work");
+ this.Invoking(_ => TypeEx.GetTypeFromManifestFull(fullNameStream, serializer.GetDeserializerSession()))
+ .Should().NotThrow("When assembly fully qualified name specified and name is correct, should work even before fix");
+ // This one was initially failing
+ this.Invoking(_ => TypeEx.GetTypeFromManifestFull(fullNameWithUnknownVersionStream, serializer.GetDeserializerSession()))
+ .Should().NotThrow("When assembly fully qualified name specified and unknown/wrong, type should be detected anyway");
+ }
+
+ [Fact]
+ public void TypeEx_ToQualifiedAssemblyName_should_strip_version_correctly_for_mscorlib_substitution()
+ {
+ var version = TypeEx.ToQualifiedAssemblyName(
+ "System.Collections.Immutable.ImmutableDictionary`2[[System.String, mscorlib,%core%],[System.Int32, mscorlib,%core%]]," +
+ " System.Collections.Immutable, Version=1.2.1.0, PublicKeyToken=b03f5f7f11d50a3a",
+ ignoreAssemblyVersion: true);
+
+ var coreAssemblyName = typeof(TypeEx).GetField("CoreAssemblyName", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null);
+ if (coreAssemblyName == null)
+ throw new Exception($"CoreAssemblyName private static field does not exist in {nameof(TypeEx)} class anymore");
+
+ version.Should().Be("System.Collections.Immutable.ImmutableDictionary`2" +
+ $"[[System.String, mscorlib{coreAssemblyName}],[System.Int32, mscorlib{coreAssemblyName}]], System.Collections.Immutable");
+ }
+
+ [Fact]
+ public void TypeEx_ToQualifiedAssemblyName_should_strip_version_correctly_for_multiple_versions_specified()
+ {
+ var version = TypeEx.ToQualifiedAssemblyName(
+ "System.Collections.Immutable.ImmutableList`1[[Foo.Bar, Foo, Version=2019.12.10.1]], " +
+ "System.Collections.Immutable, Version=1.2.2.0, PublicKeyToken=b03f5f7f11d50a3a",
+ ignoreAssemblyVersion: true);
+
+ version.Should().Be("System.Collections.Immutable.ImmutableList`1[[Foo.Bar, Foo]], System.Collections.Immutable");
+ }
+
[Fact]
public void CanSerialieCustomType_bug()
{
diff --git a/src/Hyperion.Tests/Hyperion.Tests.csproj b/src/Hyperion.Tests/Hyperion.Tests.csproj
index 782667db..cce01f9f 100644
--- a/src/Hyperion.Tests/Hyperion.Tests.csproj
+++ b/src/Hyperion.Tests/Hyperion.Tests.csproj
@@ -10,6 +10,7 @@
+
diff --git a/src/Hyperion/Extensions/TypeEx.cs b/src/Hyperion/Extensions/TypeEx.cs
index 32f31f1e..c917417f 100644
--- a/src/Hyperion/Extensions/TypeEx.cs
+++ b/src/Hyperion/Extensions/TypeEx.cs
@@ -130,11 +130,26 @@ private static Type GetTypeFromManifestName(Stream stream, DeserializerSession s
shortName = shortName.Replace("mscorlib,%core%", "System.Private.CoreLib,%core%");
}
#endif
+ return LoadTypeByName(shortName);
+ });
+ }
- var typename = ToQualifiedAssemblyName(shortName);
+ public static Type LoadTypeByName(string name)
+ {
+ try
+ {
+ // Try to load type name using strict version to avoid possible conflicts
+ // i.e. if there are different version available in GAC and locally
+ var typename = ToQualifiedAssemblyName(name, ignoreAssemblyVersion: false);
return Type.GetType(typename, true);
- });
+ }
+ catch (FileLoadException)
+ {
+ var typename = ToQualifiedAssemblyName(name, ignoreAssemblyVersion: true);
+ return Type.GetType(typename, true);
+ }
}
+
public static Type GetTypeFromManifestFull(Stream stream, DeserializerSession session)
{
var type = GetTypeFromManifestName(stream, session);
@@ -228,9 +243,16 @@ public static string GetShortAssemblyQualifiedName(this Type self)
return name;
}
- public static string ToQualifiedAssemblyName(string shortName)
+ public static string ToQualifiedAssemblyName(string shortName, bool ignoreAssemblyVersion)
{
+ // Strip out assembly version, if specified
+ if (ignoreAssemblyVersion)
+ {
+ shortName = cleanAssemblyVersionRegex.Replace(shortName, string.Empty);
+ }
+
var res = shortName.Replace(",%core%", CoreAssemblyName);
+
return res;
}
diff --git a/src/Hyperion/Hyperion.csproj b/src/Hyperion/Hyperion.csproj
index 3da7b049..e9c2a110 100644
--- a/src/Hyperion/Hyperion.csproj
+++ b/src/Hyperion/Hyperion.csproj
@@ -24,6 +24,11 @@
+
+
+ <_Parameter1>Hyperion.Tests
+
+
$(DefineConstants);NETSTANDARD16
diff --git a/src/Hyperion/ValueSerializers/TypeSerializer.cs b/src/Hyperion/ValueSerializers/TypeSerializer.cs
index db4a3059..bee8d1b9 100644
--- a/src/Hyperion/ValueSerializers/TypeSerializer.cs
+++ b/src/Hyperion/ValueSerializers/TypeSerializer.cs
@@ -66,8 +66,7 @@ public override object ReadValue(Stream stream, DeserializerSession session)
if (shortname == null)
return null;
- var name = TypeEx.ToQualifiedAssemblyName(shortname);
- var type = Type.GetType(name,true);
+ var type = TypeEx.LoadTypeByName(shortname);
//add the deserialized type to lookup
if (session.Serializer.Options.PreserveObjectReferences)
From 7f36823f43327833c1b5022c0d5f6408e081965b Mon Sep 17 00:00:00 2001
From: Aaron Stannard
Date: Mon, 20 Jan 2020 12:45:40 -0600
Subject: [PATCH 5/8] Adjust ArrayList support (#150)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Support ArrayList
* Remove wrong copyright
* Communicate between mscorlib and System.Private.CoreLib
* Strict string match
* Add a binary file generator for all .NET frameworks
* Add generated serialized files to project as suggestted in https://github.com/akkadotnet/Hyperion/pull/112#issuecomment-486078678_
* Add unit tests to test cross framework serialization and deserialization
* Readd new line
* added comment to explain null-coalescing operation
Co-authored-by: alexvaut
Co-authored-by: humhei
Co-authored-by: Deniz İrgin
---
src/Hyperion.Tests/CollectionTests.cs | 24 +++++++++++++++++++
.../EnumerableSerializerFactory.cs | 11 +++++++++
2 files changed, 35 insertions(+)
diff --git a/src/Hyperion.Tests/CollectionTests.cs b/src/Hyperion.Tests/CollectionTests.cs
index b316801a..caf0b0c6 100644
--- a/src/Hyperion.Tests/CollectionTests.cs
+++ b/src/Hyperion.Tests/CollectionTests.cs
@@ -186,6 +186,30 @@ public void CanSerializeList()
Assert.Equal(expected, actual);
}
+ [Fact]
+ public void CanSerializeArrayList()
+ {
+ var expected = new ArrayList()
+ {
+ new Something
+ {
+ BoolProp = true,
+ Else = new Else
+ {
+ Name = "Yoho"
+ },
+ Int32Prop = 999,
+ StringProp = "Yesbox!"
+ },
+ "a", 123
+ };
+
+ Serialize(expected);
+ Reset();
+ var actual = Deserialize();
+ Assert.Equal(expected, actual);
+ }
+
[Fact]
public void CanSerializeLinkedList()
{
diff --git a/src/Hyperion/SerializerFactories/EnumerableSerializerFactory.cs b/src/Hyperion/SerializerFactories/EnumerableSerializerFactory.cs
index f76c6dcb..ebadbf2b 100644
--- a/src/Hyperion/SerializerFactories/EnumerableSerializerFactory.cs
+++ b/src/Hyperion/SerializerFactories/EnumerableSerializerFactory.cs
@@ -83,6 +83,17 @@ private static Type GetEnumerableType(Type type)
private static ConstructorInfo GetEnumerableConstructor(Type type)
{
var enumerableType = GetEnumerableType(type);
+
+ /*
+ * In the event that we're serializing a non-generic IEnumerable such as an ArrayList,
+ * there aren't any generic parameters and the type returned will just be System.Object.
+ *
+ * The GetEnumerableType method extracts the generic argument from the IEnumerable and uses that
+ * by default, however it will return null only for a non-generic implementation thus we use the
+ * null-coalescing operator to specify the return type as System.Object in order to serialize ArrayList
+ * types without errors.
+ */
+ enumerableType = enumerableType ?? typeof(object);
var iEnumerableType = typeof(IEnumerable<>).MakeGenericType(enumerableType);
return enumerableType != null
? type.GetTypeInfo()
From a13c315c838218623bfba5108339cec77926b266 Mon Sep 17 00:00:00 2001
From: Aaron Stannard
Date: Mon, 20 Jan 2020 13:23:58 -0600
Subject: [PATCH 6/8] rewrote CrossFrameworkSerializationTests as xUnit theory
(#152)
---
.../CrossFrameworkSerializationTests.cs | 25 +++++++++++--------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/src/Hyperion.Tests/CrossFrameworkSerializationTests.cs b/src/Hyperion.Tests/CrossFrameworkSerializationTests.cs
index 08d5690f..69ba00fd 100644
--- a/src/Hyperion.Tests/CrossFrameworkSerializationTests.cs
+++ b/src/Hyperion.Tests/CrossFrameworkSerializationTests.cs
@@ -1,4 +1,7 @@
-using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
using Hyperion.Tests.Generator;
using Xunit;
@@ -15,22 +18,22 @@ public CrossFrameworkSerializationTests()
_originalObject = CrossFrameworkInitializer.Init();
}
- [Fact]
- public void CanSerializeCrossFramework()
+ public static IEnumerable