diff --git a/Hyperion.Tests/CollectionTests.cs b/Hyperion.Tests/CollectionTests.cs index 0743a5dc..9a8789e6 100644 --- a/Hyperion.Tests/CollectionTests.cs +++ b/Hyperion.Tests/CollectionTests.cs @@ -25,7 +25,7 @@ namespace Hyperion.Tests public class CollectionTests : TestBase { [Fact] - public void CanSerializeArrayOfTuples() + public void Serializer_should_work_with_array_of_tuples() { var expected = new[] { @@ -40,7 +40,7 @@ public void CanSerializeArrayOfTuples() } [Fact] - public void CanSerializeByteArray() + public void Serializer_should_work_with_byte_array() { var expected = new byte[] { @@ -54,7 +54,7 @@ public void CanSerializeByteArray() [Fact] - public void CanSerializeDictionary() + public void Serializer_should_work_with_dictionary() { var expected = new Dictionary { @@ -69,7 +69,7 @@ public void CanSerializeDictionary() } [Fact] - public void CanSerializeDictionaryKeysAndValuesByteChar() + public void Serializer_should_work_with_dictionary_of_byte_to_char() { var instance = new Dictionary {{0, 'z'}, {255, 'z'}, {3, char.MinValue}}; Serialize(instance); @@ -85,7 +85,7 @@ public void CanSerializeDictionaryKeysAndValuesByteChar() } [Fact] - public void CanSerializeDictionaryKeysAndValuesByteString() + public void Serializer_should_work_with_dictionary_of_byte_to_string() { var instance = new Dictionary {{0, "z"}, {255, "z"}, {3, null}}; Serialize(instance); @@ -102,7 +102,7 @@ public void CanSerializeDictionaryKeysAndValuesByteString() [Fact] - public void CanSerializeExpandoObject() + public void Serializer_should_work_with_ExpandoObject() { var obj = new ExpandoObject(); var dict = (IDictionary) obj; @@ -125,7 +125,7 @@ public void CanSerializeExpandoObject() } [Fact] - public void CanSerializeImmutableDictionary() + public void Serializer_should_work_with_immutable_dictionary() { var map = ImmutableDictionary.Empty; var serializer = new Serializer(); @@ -139,7 +139,7 @@ public void CanSerializeImmutableDictionary() } [Fact] - public void CanSerializeIntArray() + public void Serializer_should_work_with_array_of_ints() { var expected = Enumerable.Range(0, 10000).ToArray(); Serialize(expected); @@ -149,7 +149,7 @@ public void CanSerializeIntArray() } [Fact] - public void CanSerializeList() + public void Serializer_should_work_with_list() { var expected = new[] { @@ -173,7 +173,7 @@ public void CanSerializeList() } [Fact] - public void CanSerializeLinkedList() + public void Serializer_should_work_with_linked_list() { var expected = new LinkedList(new[] { @@ -197,7 +197,7 @@ public void CanSerializeLinkedList() } [Fact(Skip = "add support for multi dimentional arrays")] - public void CanSerializeMultiDimentionalArray() + public void Serializer_should_work_with_multi_dimensional_array() { var expected = new double[3, 3, 3]; for (var i = 0; i < 3; i++) @@ -217,7 +217,7 @@ public void CanSerializeMultiDimentionalArray() } [Fact] - public void CanSerializeObjectArray() + public void Serializer_should_work_with_array_of_objects() { var expected = new[] { @@ -241,7 +241,7 @@ public void CanSerializeObjectArray() } [Fact] - public void CanSerializePrimitiveArray() + public void Serializer_should_work_with_array_of_primitive_types() { var expected = new[] {DateTime.MaxValue, DateTime.MinValue, DateTime.Now, DateTime.Today}; Serialize(expected); @@ -251,7 +251,7 @@ public void CanSerializePrimitiveArray() } [Fact] - public void CanSerializeSet() + public void Serializer_should_work_with_set() { var expected = new HashSet { @@ -277,7 +277,7 @@ public void CanSerializeSet() } [Fact] - public void CanSerializeStack() + public void Serializer_should_work_with_stack() { var expected = new Stack(); expected.Push(new Something @@ -363,7 +363,7 @@ public CustomAddRange(IImmutableList inner) #endregion [Fact] - public void CanSerializeCustomEnumerableWithNonStandardAddSignature() + public void Serializer_should_work_with_custom_enumerable_with_non_standard_Add_method() { var init = new CustomAdd(ImmutableList.Empty); var expected = init.Add(1).Add(2); @@ -375,7 +375,7 @@ public void CanSerializeCustomEnumerableWithNonStandardAddSignature() } [Fact] - public void CanSerializeCustomEnumerableWithNonStandardAddRangeSignature() + public void Serializer_should_work_with_custom_enumerable_with_non_standard_AddRange_method() { var init = new CustomAddRange(ImmutableList.Empty); var expected = init.AddRange("label", new []{ 1, 2, 3 }); @@ -490,7 +490,7 @@ public void Add(NotKnown item) } [Fact] - public void CanInstantiateSerializerForCollectionWithAmbiguousAddMethod() + public void Serializer_should_work_with_collection_with_ambiguous_Add_method() { var serializer = new Serializer( new SerializerOptions(knownTypes: new List {typeof(DerivedContainer)}, diff --git a/Hyperion.Tests/CustomObjectTests.cs b/Hyperion.Tests/CustomObjectTests.cs index 46ce0b57..7f9e0590 100644 --- a/Hyperion.Tests/CustomObjectTests.cs +++ b/Hyperion.Tests/CustomObjectTests.cs @@ -19,8 +19,9 @@ private class PrivateType { public int IntProp { get; set; } } + [Fact] - public void CanSerializePrivateType() + public void Serializer_should_work_with_non_public_types() { var expected = new PrivateType() { @@ -33,7 +34,7 @@ public void CanSerializePrivateType() } [Fact] - public void CanSerializeTypeObject() + public void Serializer_should_work_with_Type() { var expected = typeof(ArgumentException); Serialize(expected); @@ -43,7 +44,7 @@ public void CanSerializeTypeObject() } [Fact] - public void CanSerializeNull() + public void Serializer_should_work_with_null() { var expected = new Something { @@ -61,7 +62,7 @@ public void CanSerializeNull() //all custom exception information will be lost. //only message, inner exception, stacktrace and the bare minimum will be preserved. [Fact] - public void CanSerializeException() + public void Serializer_should_work_with_Exceptions() { var expected = new Exception("hello wire"); Serialize(expected); @@ -72,7 +73,7 @@ public void CanSerializeException() } [Fact] - public void CanSerializePolymorphicObject() + public void Serializer_should_work_with_polymorphic_objects() { var expected = new Something { @@ -89,7 +90,7 @@ public void CanSerializePolymorphicObject() } [Fact] - public void CanSerializeStruct() + public void Serializer_should_work_with_structs() { var expected = new StuctValue { @@ -97,7 +98,6 @@ public void CanSerializeStruct() Prop2 = 123, }; - Serialize(expected); Reset(); var actual = Deserialize(); @@ -105,7 +105,7 @@ public void CanSerializeStruct() } [Fact] - public void CanSerializeObject() + public void Serializer_should_work_with_custom_classes() { var expected = new Something { @@ -114,8 +114,7 @@ public void CanSerializeObject() NullableInt32PropHasValue = 888, StringProp = "hello", }; - - + Serialize(expected); Reset(); var actual = Deserialize(); @@ -123,7 +122,7 @@ public void CanSerializeObject() } [Fact] - public void CanSerializeObjects() + public void Serializer_should_work_with_custom_classes_2() { var expected1 = new Something { @@ -147,7 +146,7 @@ public void CanSerializeObjects() } [Fact] - public void CanSerializeTuple() + public void Serializer_should_work_with_tuples() { var expected = Tuple.Create("hello"); Serialize(expected); @@ -157,7 +156,7 @@ public void CanSerializeTuple() } [Fact] - public void CanEmptyObject() + public void Serializer_should_work_with_objects_without_any_fields() { var expected = new Empty(); @@ -168,7 +167,7 @@ public void CanEmptyObject() } [Fact] - public void CanSerializeObjectsKnownTypes() + public void Serializer_should_work_with_objects_marked_as_known_types() { CustomInit(new Serializer(new SerializerOptions(knownTypes:new[] {typeof(Something)}))); var expected1 = new Something diff --git a/Hyperion.Tests/CyclicTests.cs b/Hyperion.Tests/CyclicTests.cs index 59bcd4bc..033a7d21 100644 --- a/Hyperion.Tests/CyclicTests.cs +++ b/Hyperion.Tests/CyclicTests.cs @@ -16,7 +16,7 @@ namespace Hyperion.Tests public class CyclicTests { [Fact] - public void CanSerializeDeepCyclicReferences() + public void Serializer_should_work_with_deeply_cycled_object_references() { var stream = new MemoryStream(); var serializer = new Serializer(new SerializerOptions(versionTolerance: true, preserveObjectReferences: true)); @@ -37,7 +37,7 @@ public void CanSerializeDeepCyclicReferences() } [Fact] - public void CanSerializeDictionaryPreserveObjectReferences() + public void Serializer_should_work_with_dictionary_and_preserve_object_references() { var stream = new MemoryStream(); var serializer = new Serializer(new SerializerOptions(versionTolerance: true, preserveObjectReferences: true)); @@ -61,7 +61,7 @@ public void CanSerializeDictionaryPreserveObjectReferences() //From Orleans [Fact] - public void CanSerializeDictionaryPreserveObjectReferences2() + public void Serializer_should_work_with_dictionary_and_preserve_object_references_2() { var stream = new MemoryStream(); var serializer = new Serializer(new SerializerOptions(versionTolerance: true, preserveObjectReferences: true)); @@ -88,7 +88,7 @@ public void CanSerializeDictionaryPreserveObjectReferences2() [Fact] - public void CanSerializeCyclicReferences() + public void Serializer_should_work_with_cyclic_references() { var stream = new MemoryStream(); var serializer = new Serializer(new SerializerOptions(versionTolerance: true, preserveObjectReferences: true)); @@ -104,7 +104,7 @@ public void CanSerializeCyclicReferences() } [Fact] - public void CanSerializeMultiLevelCyclicReferences() + public void Serializer_should_work_with_multilevel_cyclic_object_references() { var stream = new MemoryStream(); var serializer = new Serializer(new SerializerOptions(preserveObjectReferences: true)); diff --git a/Hyperion.Tests/DelegateTests.cs b/Hyperion.Tests/DelegateTests.cs index b9cbd332..4228603f 100644 --- a/Hyperion.Tests/DelegateTests.cs +++ b/Hyperion.Tests/DelegateTests.cs @@ -31,7 +31,7 @@ public void Create() } [Fact] - public void CanSerializeMemberMethod() + public void Serializer_should_work_with_member_method() { var stream = new MemoryStream(); var serializer = new Serializer(new SerializerOptions()); @@ -46,7 +46,7 @@ public void CanSerializeMemberMethod() } [Fact] - public void CanSerializeDelegate() + public void Serializer_should_work_with_delegates() { var stream = new MemoryStream(); var serializer = new Serializer(new SerializerOptions()); @@ -68,7 +68,7 @@ private static int StaticFunc(int a) } [Fact] - public void CanSerializeStaticDelegate() + public void Serializer_should_work_with_static_delegates() { var stream = new MemoryStream(); var serializer = new Serializer(new SerializerOptions()); @@ -85,7 +85,7 @@ public void CanSerializeStaticDelegate() } [Fact] - public void CanSerializeObjectWithClosure() + public void Serializer_should_work_with_objects_with_closures() { var stream = new MemoryStream(); var serializer = new Serializer(new SerializerOptions()); diff --git a/Hyperion.Tests/EncapsulationTests.cs b/Hyperion.Tests/EncapsulationTests.cs index 004b8373..ee42c775 100644 --- a/Hyperion.Tests/EncapsulationTests.cs +++ b/Hyperion.Tests/EncapsulationTests.cs @@ -67,7 +67,7 @@ public EncapsulationTests() } [Fact] - public void CanSerializeObjectsWithNonPublicConstructor() + public void Serializer_should_work_with_types_having_non_public_constructors() { var actual = ClassWithPrivCtor.Create(55); var deserialized = Roundtrip(actual); @@ -76,7 +76,7 @@ public void CanSerializeObjectsWithNonPublicConstructor() } [Fact] - public void CanSerializeObjectsWithNonPublicConstructorInCollections() + public void Serializer_should_work_with_collections_of_types_having_non_public_constructors() { IList actual = new List { @@ -94,7 +94,7 @@ public void CanSerializeObjectsWithNonPublicConstructorInCollections() } [Fact] - public void CanSerializeNonPublicClasses() + public void Serializer_should_work_with_non_public_classes() { var actual = new NonPublicClass(123); var deserialized = Roundtrip(actual); @@ -103,7 +103,7 @@ public void CanSerializeNonPublicClasses() } [Fact] - public void CanSerializeNonPublicClassesInCollections() + public void Serializer_should_work_with_collections_of_non_public_classes() { IList actual = new List { @@ -121,7 +121,7 @@ public void CanSerializeNonPublicClassesInCollections() } [Fact] - public void CanSerializeStructsWithReadonlyFields() + public void Serializer_should_work_with_structs_having_readonly_fields() { var actual = new StructWithReadonlyFields(123, "hello"); var deserialized = Roundtrip(actual); @@ -130,7 +130,7 @@ public void CanSerializeStructsWithReadonlyFields() } [Fact] - public void CanSerializeStructsWithReadonlyFieldsInCollections() + public void Serializer_should_work_with_collections_of_structs_having_readonly_fields() { IList actual = new List { diff --git a/Hyperion.Tests/ExpressionTests.cs b/Hyperion.Tests/ExpressionTests.cs index c977f8f2..0b65d08e 100644 --- a/Hyperion.Tests/ExpressionTests.cs +++ b/Hyperion.Tests/ExpressionTests.cs @@ -44,7 +44,7 @@ protected DummyException( } [Fact] - public void CanSerializeFieldInfo() + public void Serializer_should_work_with_FieldInfo() { var fieldInfo = typeof(Dummy).GetField("TestField"); var serializer = new Hyperion.Serializer(); @@ -59,7 +59,7 @@ public void CanSerializeFieldInfo() } [Fact] - public void CanSerializePropertyInfo() + public void Serializer_should_work_with_PropertyInfo() { var propertyInfo = typeof(Dummy).GetProperty("TestProperty"); var serializer = new Hyperion.Serializer(); @@ -74,7 +74,7 @@ public void CanSerializePropertyInfo() } [Fact] - public void CanSerializeMethodInfo() + public void Serializer_should_work_with_MethodInfo() { var methodInfo = typeof(Dummy).GetMethod("Fact"); var serializer = new Hyperion.Serializer(); @@ -89,7 +89,7 @@ public void CanSerializeMethodInfo() } [Fact] - public void CanSerializeSymbolDocumentInfo() + public void Serializer_should_work_with_SymbolDocumentInfo() { var info = Expression.SymbolDocument("testFile"); var serializer = new Hyperion.Serializer(); @@ -104,7 +104,7 @@ public void CanSerializeSymbolDocumentInfo() } [Fact] - public void CanSerializeConstructorInfo() + public void Serializer_should_work_with_ConstructorInfo() { var constructorInfo = typeof(Dummy).GetConstructor(new[] { typeof(string) }); var serializer = new Hyperion.Serializer(); @@ -119,7 +119,7 @@ public void CanSerializeConstructorInfo() } [Fact] - public void CanSerializeConstantExpression() + public void Serializer_should_work_with_ConstantExpression() { var expr = Expression.Constant(12); var serializer = new Hyperion.Serializer(); @@ -136,7 +136,7 @@ public void CanSerializeConstantExpression() } [Fact] - public void CanSerializeUnaryExpression() + public void Serializer_should_work_with_UnaryExpression() { var expr = Expression.Decrement(Expression.Constant(1)); var serializer = new Hyperion.Serializer(); @@ -154,7 +154,7 @@ public void CanSerializeUnaryExpression() } [Fact] - public void CanSerializeBinaryExpression() + public void Serializer_should_work_with_BinaryExpression() { var expr = Expression.Add(Expression.Constant(1), Expression.Constant(2)); var serializer = new Hyperion.Serializer(); @@ -170,7 +170,7 @@ public void CanSerializeBinaryExpression() } [Fact] - public void CanSerializeIndexExpression() + public void Serializer_should_work_with_IndexExpression() { var value = new[] {1, 2, 3}; var arrayExpr = Expression.Constant(value); @@ -195,7 +195,7 @@ public void CanSerializeIndexExpression() } [Fact] - public void CanSerializeMemberAssignment() + public void Serializer_should_work_with_MemberAssignment() { var property = typeof(Dummy).GetProperty("TestProperty"); var expr = Expression.Bind(property.SetMethod, Expression.Constant(9)); @@ -213,7 +213,7 @@ public void CanSerializeMemberAssignment() } [Fact] - public void CanSerializeConditionalExpression() + public void Serializer_should_work_with_ConditionalExpression() { var expr = Expression.Condition(Expression.Constant(true), Expression.Constant(1), Expression.Constant(2)); var serializer = new Hyperion.Serializer(); @@ -232,7 +232,7 @@ public void CanSerializeConditionalExpression() } [Fact] - public void CanSerializeBlockExpression() + public void Serializer_should_work_with_BlockExpression() { var expr = Expression.Block(new[] { Expression.Constant(1), Expression.Constant(2), Expression.Constant(3) }); var serializer = new Hyperion.Serializer(); @@ -252,7 +252,7 @@ public void CanSerializeBlockExpression() } [Fact] - public void CanSerializeLabelTarget() + public void Serializer_should_work_with_LabelTarget() { var label = Expression.Label(typeof(int), "testLabel"); var serializer = new Hyperion.Serializer(); @@ -268,7 +268,7 @@ public void CanSerializeLabelTarget() } [Fact] - public void CanSerializeLabelExpression() + public void Serializer_should_work_with_LabelExpression() { var label = Expression.Label(typeof(int), "testLabel"); var expr = Expression.Label(label, Expression.Constant(2)); @@ -287,7 +287,7 @@ public void CanSerializeLabelExpression() } [Fact] - public void CanSerializeMethodCallExpression() + public void Serializer_should_work_with_MethodCallExpression() { var methodInfo = typeof(Dummy).GetMethod("Fact"); var expr = Expression.Call(Expression.Constant(new Dummy()), methodInfo, Expression.Constant("test string")); @@ -308,7 +308,7 @@ public void CanSerializeMethodCallExpression() } [Fact] - public void CanSerializeDefaultExpression() + public void Serializer_should_work_with_DefaultExpression() { var expr = Expression.Default(typeof(int)); var serializer = new Hyperion.Serializer(); @@ -324,7 +324,7 @@ public void CanSerializeDefaultExpression() } [Fact] - public void CanSerializeParameterExpression() + public void Serializer_should_work_with_ParameterExpression() { var expr = Expression.Parameter(typeof(int), "p1"); var serializer = new Hyperion.Serializer(); @@ -341,7 +341,7 @@ public void CanSerializeParameterExpression() } [Fact] - public void CanSerializeTargetInvocationException() + public void Serializer_should_work_with_TargetInvocationException() { var exc = new TargetInvocationException(null); var serializer = new Hyperion.Serializer(); @@ -357,7 +357,7 @@ public void CanSerializeTargetInvocationException() } [Fact] - public void CanSerializeObjectDisposedException() + public void Serializer_should_work_with_ObjectDisposedException() { var exc = new ObjectDisposedException("Object is already disposed", new ArgumentException("One level deeper")); var serializer = new Hyperion.Serializer(); @@ -376,7 +376,7 @@ public void CanSerializeObjectDisposedException() } [Fact] - public void CanSerializeCatchBlock() + public void Serializer_should_work_with_CatchBlock() { var expr = Expression.Catch(typeof(DummyException), Expression.Constant(2)); var serializer = new Hyperion.Serializer(); @@ -392,7 +392,7 @@ public void CanSerializeCatchBlock() } [Fact] - public void CanSerializeGotoExpression() + public void Serializer_should_work_with_GotoExpression() { var label = Expression.Label(typeof(void), "testLabel"); var expr = Expression.Continue(label); @@ -411,7 +411,7 @@ public void CanSerializeGotoExpression() } [Fact] - public void CanSerializeNewExpression() + public void Serializer_should_work_with_NewExpression() { var ctor = typeof(Dummy).GetConstructor(new[] { typeof(string) }); var expr = Expression.New(ctor, Expression.Constant("test param")); @@ -431,7 +431,7 @@ public void CanSerializeNewExpression() } [Fact] - public void CanSerializeDebugInfoExpression() + public void Serializer_should_work_with_DebugInfoExpression() { var info = Expression.SymbolDocument("testFile"); var expr = Expression.DebugInfo(info, 1, 2, 3, 4); @@ -453,7 +453,7 @@ public void CanSerializeDebugInfoExpression() } [Fact] - public void CanSerializeLambdaExpression() + public void Serializer_should_work_with_LambdaExpression() { var methodInfo = typeof(Dummy).GetMethod("Fact"); var param = Expression.Parameter(typeof (Dummy), "dummy"); @@ -476,7 +476,7 @@ public void CanSerializeLambdaExpression() } [Fact] - public void CanSerializeLambdaExpressionContainingGenericMethod() { + public void Serializer_should_work_with_lambda_expression_having_generic_methods() { Expression> expr = dummy => dummy.TestField.Contains('s'); var serializer = new Serializer(new SerializerOptions(preserveObjectReferences: true)); using (var ms = new MemoryStream()) @@ -491,7 +491,7 @@ public void CanSerializeLambdaExpressionContainingGenericMethod() { } [Fact] - public void CanSerializeInvocationExpression() + public void Serializer_should_work_with_InvocationExpression() { var methodInfo = typeof(Dummy).GetMethod("Fact"); var param = Expression.Parameter(typeof(Dummy), "dummy"); @@ -512,7 +512,7 @@ public void CanSerializeInvocationExpression() } [Fact] - public void CanSerializeElementInit() + public void Serializer_should_work_with_ElementInit() { var listAddMethod = typeof (List).GetMethod("Add"); var expr = Expression.ElementInit(listAddMethod, Expression.Constant(1)); @@ -530,7 +530,7 @@ public void CanSerializeElementInit() } [Fact] - public void CanSerializeLoopExpression() + public void Serializer_should_work_with_LoopExpression() { var breakLabel = Expression.Label(typeof (void), "break"); var continueLabel = Expression.Label(typeof(void), "cont"); diff --git a/Hyperion.Tests/FSharpTests.cs b/Hyperion.Tests/FSharpTests.cs index 634b1b80..a9060981 100644 --- a/Hyperion.Tests/FSharpTests.cs +++ b/Hyperion.Tests/FSharpTests.cs @@ -23,7 +23,7 @@ public class FSharpTests : TestBase { [Fact] - public void CanSerializeFSharpMap() + public void Serializer_should_work_with_fsharp_Map() { var expected = TestMap.createRecordWithMap; Serialize(expected); @@ -34,7 +34,7 @@ public void CanSerializeFSharpMap() [Fact] - public void CanSerializeFSharpList() + public void Serializer_should_work_with_fsharp_List() { var expected = ListModule.OfArray(new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }); Serialize(expected); @@ -44,7 +44,7 @@ public void CanSerializeFSharpList() } [Fact] - public void CanSerializeSimpleDU() + public void Serializer_should_work_with_simple_discriminated_unions() { var expected = DU1.NewA(1); Serialize(expected); @@ -54,7 +54,7 @@ public void CanSerializeSimpleDU() } [Fact] - public void CanSerializeNestedDU() + public void Serializer_should_work_with_nested_discriminated_unions() { var expected = DU2.NewC(DU1.NewA(1)); Serialize(expected); @@ -64,7 +64,7 @@ public void CanSerializeNestedDU() } [Fact] - public void CanSerializeOptionalDU() + public void Serializer_should_work_with_optional_discriminated_unions() { var expected = DU2.NewE(FSharpOption.Some(DU1.NewA(1))); Serialize(expected); @@ -74,7 +74,7 @@ public void CanSerializeOptionalDU() } [Fact] - public void CanSerializeOption() + public void Serializer_should_work_with_options() { var expected = FSharpOption.Some("hello"); Serialize(expected); @@ -93,7 +93,7 @@ protected override void OnReceive(object message) #endif [Fact] - public void CanSerializeUser() + public void Serializer_should_work_with_fsharp_records() { var expected = new User("foo", new FSharpOption(null), "hello"); Serialize(expected); @@ -108,7 +108,7 @@ public void CanSerializeUser() //FIXME: make F# quotations and Async serializable //[Fact] - public void CanSerializeQuotation() + public void Serializer_should_work_with_fsharp_quotations_expressions() { var expected = TestQuotations.Quotation; Serialize(expected); diff --git a/Hyperion.Tests/ISerializableTests.cs b/Hyperion.Tests/ISerializableTests.cs index 0f73e0c2..a37c2b95 100644 --- a/Hyperion.Tests/ISerializableTests.cs +++ b/Hyperion.Tests/ISerializableTests.cs @@ -108,7 +108,7 @@ public void OnDeserialization(object sender) #endregion [Fact] - public void CanIgnoreFieldsWithNonSerializedAttribute() + public void Serializer_should_ignore_fields_marked_with_NonSerialized_attribute() { var expected = new NonSerializedTest() { Field1 = 235, @@ -123,7 +123,7 @@ public void CanIgnoreFieldsWithNonSerializedAttribute() } [Fact(Skip="Not implemented yet")] - public void SkipNonSerializedAttributeIfNoSerilizedAttribute() + public void Serializer_should_skip_NonSerialized_attribute_if_Serialized_attribute_was_not_used() { var expected = new NonSerializedWithoutSerializableTest() { Field1 = 235, @@ -138,7 +138,7 @@ public void SkipNonSerializedAttributeIfNoSerilizedAttribute() } [Fact] - public void CanSerializeClassesWithISerializable() + public void Serializer_should_work_with_types_implementing_ISerializable_interface() { var expected = new Person("Scott", "Hanselman"); @@ -150,7 +150,7 @@ public void CanSerializeClassesWithISerializable() } [Fact(Skip="Not implemented yet")] - public void ShouldNotThrowIfNoConstructorWithSerializationInfo() + public void Serializer_should_not_fail_if_there_was_no_constructor_with_SerializationInfo() { var expected = new PersonWithoutConstructor("Scott"); @@ -161,7 +161,7 @@ public void ShouldNotThrowIfNoConstructorWithSerializationInfo() } [Fact] - public void ShouldThrowOnNonSerializableEvent() + public void Serializer_should_fail_on_non_serializable_event() { var expected = new NotSerializableEvent(true); @@ -169,7 +169,7 @@ public void ShouldThrowOnNonSerializableEvent() } [Fact] - public void SupportsIDeserializationCallback() + public void Serializer_should_make_use_of_IDeserializationCallback() { var expected = new PersonWithIDeserializationCallback { FirstName = "Scott" }; diff --git a/Hyperion.Tests/IlCompilerTests.cs b/Hyperion.Tests/IlCompilerTests.cs index d1cbc3c4..8d62f407 100644 --- a/Hyperion.Tests/IlCompilerTests.cs +++ b/Hyperion.Tests/IlCompilerTests.cs @@ -59,7 +59,7 @@ public class IlCompilerTests private static readonly MethodInfo SetStatic = typeof(Dummy).GetMethod(nameof(Dummy.SetStatic)); [Fact] - public void CanCallStaticMethodUsingParameter() + public void IlCompiler_should_call_static_methods_with_parameters() { var c = new IlCompiler>(); var param = c.Parameter("dummy"); @@ -71,7 +71,7 @@ public void CanCallStaticMethodUsingParameter() } [Fact] - public void CanCallInstanceMethodOnParameter() + public void IlCompiler_should_call_instance_methods_with_parameters() { var c = new IlCompiler>(); var param = c.Parameter("dummy"); @@ -84,7 +84,7 @@ public void CanCallInstanceMethodOnParameter() [Fact] - public void CanModifyParameter() + public void IlCompiler_can_modify_parameters() { var c = new IlCompiler>(); var param = c.Parameter("dummy"); @@ -97,7 +97,7 @@ public void CanModifyParameter() } [Fact] - public void CanCreateEmptyMethodWithArguments() + public void IlCompiler_can_create_empty_method_with_args() { var c = new IlCompiler>(); var a = c.Compile(); @@ -105,7 +105,7 @@ public void CanCreateEmptyMethodWithArguments() } [Fact] - public void CanCreateEmptyMethodWithReturnType() + public void IlCompiler_can_create_empty_method_with_return_type() { var c = new IlCompiler>(); var b = c.Constant(true); @@ -116,7 +116,7 @@ public void CanCreateEmptyMethodWithReturnType() } [Fact] - public void CanReturnConstantString() + public void IlCompiler_can_return_constant_string() { var c = new IlCompiler>(); var b = c.Constant("hello"); @@ -127,7 +127,7 @@ public void CanReturnConstantString() } [Fact] - public void CanCreateEmptyMethod() + public void IlCompiler_can_create_empty_method() { var c = new IlCompiler(); var a = c.Compile(); @@ -135,7 +135,7 @@ public void CanCreateEmptyMethod() } [Fact] - public void CanCreateObject() + public void IlCompiler_can_create_an_object() { var c = new IlCompiler>(); var obj = c.NewObject(typeof(Dummy)); @@ -145,7 +145,7 @@ public void CanCreateObject() } [Fact] - public void CanStoreBoolInField() + public void IlCompiler_can_assign_value_to_a_field() { var c = new IlCompiler(); var True = c.Constant(true); @@ -157,7 +157,7 @@ public void CanStoreBoolInField() } [Fact] - public void CanCastToAndFromObject() + public void IlCompiler_can_box_and_unbox() { var c = new IlCompiler(); @@ -173,7 +173,7 @@ public void CanCastToAndFromObject() } [Fact] - public void CanCreateObjectAndStoreInVar() + public void IlCompiler_can_initialize_variables() { var c = new IlCompiler(); var variable = c.Variable("dummy"); @@ -186,7 +186,7 @@ public void CanCreateObjectAndStoreInVar() [Fact] - public void ReadSimulationFakeTupleString() + public void IlCompiler_can_pass_read_simulation_on_fake_tupled_string() { var value = new FakeTupleString("Hello"); var type = value.GetType(); @@ -207,7 +207,7 @@ public void ReadSimulationFakeTupleString() [Fact] - public void ReadSimulationOptionString() + public void IlCompiler_can_pass_read_simulation_on_fsharp_option_of_string() { var value = FSharpOption.Some("abc"); var type = value.GetType(); @@ -226,7 +226,7 @@ public void ReadSimulationOptionString() } [Fact] - public void ReadSimulationTupleString() + public void IlCompiler_can_pass_read_simulation_on_tuple_of_string() { var value = Tuple.Create("Hello"); var type = value.GetType(); @@ -246,7 +246,7 @@ public void ReadSimulationTupleString() } [Fact] - public void ReadSimulation() + public void IlCompiler_can_pass_read_simulation() { var serializer = new Serializer(new SerializerOptions(knownTypes:new List() {typeof(Poco)})); var session = new DeserializerSession(serializer); diff --git a/Hyperion.Tests/ImmutableCollectionsTests.cs b/Hyperion.Tests/ImmutableCollectionsTests.cs index a8911cc2..475774cd 100644 --- a/Hyperion.Tests/ImmutableCollectionsTests.cs +++ b/Hyperion.Tests/ImmutableCollectionsTests.cs @@ -85,7 +85,7 @@ private static bool SeqEquals(IEnumerable first, IEnumerable second) #endregion [Fact] - public void CanSerializeImmutableHashSet() + public void Serializer_should_work_with_ImmutableHashSet() { var expected = ImmutableHashSet.CreateRange(new[] { @@ -110,7 +110,7 @@ public void CanSerializeImmutableHashSet() } [Fact] - public void CanSerializeImmutableSortedSet() + public void Serializer_should_work_with_ImmutableSortedSet() { var expected = ImmutableSortedSet.CreateRange(new[] { @@ -126,7 +126,7 @@ public void CanSerializeImmutableSortedSet() } [Fact] - public void CanSerializeImmutableDictionary() + public void Serializer_should_work_with_ImmutableDictionary() { var expected = ImmutableDictionary.CreateRange(new Dictionary { @@ -152,7 +152,7 @@ public void CanSerializeImmutableDictionary() } [Fact] - public void CanSerializeImmutableQueue() + public void Serializer_should_work_with_ImmutableQueue() { var expected = ImmutableQueue.CreateRange(new[] { @@ -178,7 +178,7 @@ public void CanSerializeImmutableQueue() } [Fact] - public void CanSerializeImmutableStack() + public void Serializer_should_work_with_ImmutableStack() { var expected = ImmutableStack.CreateRange(new[] { @@ -203,7 +203,7 @@ public void CanSerializeImmutableStack() } [Fact] - public void CanSerializeImmutableArray() + public void Serializer_should_work_with_ImmutableArray() { var expected = ImmutableArray.CreateRange(new[] { @@ -229,7 +229,7 @@ public void CanSerializeImmutableArray() } [Fact] - public void CanSerializeImmutableList() + public void Serializer_should_work_with_ImmutableList() { var expected = ImmutableList.CreateRange(new[] { @@ -255,7 +255,7 @@ public void CanSerializeImmutableList() } [Fact] - public void CanSerializeImmutableCollectionsReferencedThroughInterfaceInFields() + public void Serializer_should_work_with_types_having_immutable_collections_referenced_through_interface() { var expected = new TestClass( dictionary: ImmutableDictionary.CreateRange(new[] diff --git a/Hyperion.Tests/InterfaceTests.cs b/Hyperion.Tests/InterfaceTests.cs index 0dbaa838..9521407c 100644 --- a/Hyperion.Tests/InterfaceTests.cs +++ b/Hyperion.Tests/InterfaceTests.cs @@ -32,7 +32,7 @@ public class Foo : IFoo } [Fact] - public void CanSerializeInterfaceField() + public void Serializer_should_work_with_types_having_interface_fields() { var b = new Bar { diff --git a/Hyperion.Tests/PreserveObjectReferencesTests.cs b/Hyperion.Tests/PreserveObjectReferencesTests.cs new file mode 100644 index 00000000..81172e6e --- /dev/null +++ b/Hyperion.Tests/PreserveObjectReferencesTests.cs @@ -0,0 +1,208 @@ +#region copyright +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015-2016 AsynkronIT +// Copyright (C) 2016-2016 Akka.NET Team +// +// ----------------------------------------------------------------------- +#endregion + +using System; +using System.IO; +using Xunit; + +namespace Hyperion.Tests +{ + public class PreserveObjectReferencesTests + { + [Fact] + public void When_preserve_object_references_is_off_globally_and_PreserveReferences_is_used_references_should_be_preserved() + { + var serializer = new Serializer(new SerializerOptions(preserveObjectReferences: false)); + var expected = new PreservedObject { First = "first", Second = 1234 }; + + AssertPreserveObjectReferencesWorks(serializer, expected, checkReferenceEquality: true); + } + + [Fact] + public void When_preserve_object_references_is_off_globally_and_PreserveReferences_is_used_in_nested_objects_references_should_be_preserved() + { + var serializer = new Serializer(new SerializerOptions(preserveObjectReferences: false)); + var x = new PreservedObject { First = "first", Second = 1234 }; + var expected = new Parent(123, x); + + AssertPreserveObjectReferencesWorks(serializer, expected, checkReferenceEquality: false); + } + + [Fact] + public void When_preserve_object_references_is_on_globally_references_should_be_preserved_for_any_object() + { + var serializer = new Serializer(new SerializerOptions(preserveObjectReferences: true)); + var expected = new Something { Int32Prop = 1235, StringProp = "hello", BoolProp = true }; + + AssertPreserveObjectReferencesWorks(serializer, expected, checkReferenceEquality: true); + } + + [Fact] + public void When_preserve_object_references_is_on_globally_and_PreserveReferences_is_disabled_references_should_not_be_preserved() + { + var serializer = new Serializer(new SerializerOptions(preserveObjectReferences: true)); + var expected = new UnpreservedObject { First = "first", Second = 1234 }; + + var serializerSession = new SerializerSession(serializer); + var deserializerSession = new DeserializerSession(serializer); + + using (var stream1 = new MemoryStream()) + using (var stream2 = new MemoryStream()) + { + serializer.Serialize(expected, stream1, serializerSession); + var payload1 = stream1.ToArray(); + stream1.Position = 0; + var actual1 = serializer.Deserialize(stream1, deserializerSession); + + serializer.Serialize(expected, stream2, serializerSession); + var payload2 = stream2.ToArray(); + stream2.Position = 0; + var actual2 = serializer.Deserialize(stream1, deserializerSession); + + // all objects should be equal to each other before/after serialization + Assert.Equal(expected, actual1); + Assert.Equal(expected, actual2); + Assert.Equal(actual1, actual2); + Assert.NotSame(actual1, actual2); + + // payloads should be equal - even thou we have preserveObjectReferences = true, + // for this type it's turned off + Assert.Equal(payload1.Length, payload2.Length); + } + } + + private static void AssertPreserveObjectReferencesWorks(Serializer serializer, T expected, bool checkReferenceEquality) + { + var serializerSession = new SerializerSession(serializer); + var deserializerSession = new DeserializerSession(serializer); + + using (var stream1 = new MemoryStream()) + using (var stream2 = new MemoryStream()) + { + serializer.Serialize(expected, stream1, serializerSession); + var payload1 = stream1.ToArray(); + stream1.Position = 0; + var actual1 = serializer.Deserialize(stream1, deserializerSession); + + serializer.Serialize(expected, stream2, serializerSession); + var payload2 = stream2.ToArray(); + stream2.Position = 0; + var actual2 = serializer.Deserialize(stream1, deserializerSession); + + // all objects should be equal to each other before/after serialization + Assert.Equal(expected, actual1); + Assert.Equal(expected, actual2); + + if (checkReferenceEquality) + Assert.Same(actual1, actual2); + else + Assert.Equal(actual1, actual2); + + // payloads should not be equal - in fact second time, second payload should be smaller + // since we reused metadata from session + Assert.NotEqual(payload1, payload2); + Assert.True(payload2.Length < payload1.Length, "on second serialization the result payload should be smaller"); + } + } + } + + public sealed class Parent : IEquatable + { + public int Id { get; } + + public PreservedObject Inner { get; } + + public Parent(int id, PreservedObject inner) + { + Id = id; + Inner = inner; + } + + public bool Equals(Parent other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Id == other.Id && Equals(Inner, other.Inner); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj is Parent && Equals((Parent) obj); + } + + public override int GetHashCode() + { + unchecked + { + return (Id * 397) ^ (Inner != null ? Inner.GetHashCode() : 0); + } + } + } + + [PreserveReferences] + public sealed class PreservedObject : IEquatable + { + public string First { get; set; } + public int Second { get; set; } + + public bool Equals(PreservedObject other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return string.Equals(First, other.First) && Second == other.Second; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj is PreservedObject && Equals((PreservedObject)obj); + } + + public override int GetHashCode() + { + unchecked + { + return ((First != null ? First.GetHashCode() : 0) * 397) ^ Second; + } + } + } + + [PreserveReferences(false)] + public sealed class UnpreservedObject : IEquatable + { + public string First { get; set; } + public int Second { get; set; } + + public bool Equals(UnpreservedObject other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return string.Equals(First, other.First) && Second == other.Second; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj is UnpreservedObject && Equals((UnpreservedObject)obj); + } + + public override int GetHashCode() + { + unchecked + { + return ((First != null ? First.GetHashCode() : 0) * 397) ^ Second; + } + } + } + +} \ No newline at end of file diff --git a/Hyperion.Tests/PrimitivesTests.cs b/Hyperion.Tests/PrimitivesTests.cs index 8a050905..20c740db 100644 --- a/Hyperion.Tests/PrimitivesTests.cs +++ b/Hyperion.Tests/PrimitivesTests.cs @@ -16,158 +16,158 @@ namespace Hyperion.Tests public class PrimitivesTest : TestBase { [Fact] - public void CanSerializeTuple1() + public void Serializer_should_work_with_Tuple1() { SerializeAndAssert(Tuple.Create("abc")); } [Fact] - public void CanSerializeTuple2() + public void Serializer_should_work_with_Tuple2() { SerializeAndAssert(Tuple.Create(1, 123)); } [Fact] - public void CanSerializeTuple3() + public void Serializer_should_work_with_Tuple3() { SerializeAndAssert(Tuple.Create(1, 2, 3)); } [Fact] - public void CanSerializeTuple4() + public void Serializer_should_work_with_Tuple4() { SerializeAndAssert(Tuple.Create(1, 2, 3, 4)); } [Fact] - public void CanSerializeTuple5() + public void Serializer_should_work_with_Tuple5() { SerializeAndAssert(Tuple.Create(1, 2, 3, 4, 5)); } [Fact] - public void CanSerializeTuple6() + public void Serializer_should_work_with_Tuple6() { SerializeAndAssert(Tuple.Create(1, 2, 3, 4, 5, 6)); } [Fact] - public void CanSerializeTuple7() + public void Serializer_should_work_with_Tuple7() { SerializeAndAssert(Tuple.Create(1, 2, 3, 4, 5, 6, 7)); } [Fact] - public void CanSerializeTuple8() + public void Serializer_should_work_with_Tuple8() { SerializeAndAssert(Tuple.Create(1, 2, 3, 4, 5, 6, 7, 8)); } [Fact] - public void CanSerializeBool() + public void Serializer_should_work_with_Bool() { SerializeAndAssert(true); } [Fact] - public void CanSerializeGuid() + public void Serializer_should_work_with_Guid() { SerializeAndAssert(Guid.NewGuid()); } [Fact] - public void CanSerializeDateTimeUtc() + public void Serializer_should_work_with_DateTime_UTC() { SerializeAndAssert(DateTime.UtcNow); } [Fact] - public void CanSerializeDateTimeLocal() + public void Serializer_should_work_with_DateTime_local() { SerializeAndAssert(new DateTime(DateTime.Now.Ticks, DateTimeKind.Local)); } [Fact] - public void CanSerializeDateTimeOffsetNow() + public void Serializer_should_work_with_DateTimeOffset_now() { SerializeAndAssert(DateTimeOffset.Now); } [Fact] - public void CanSerializeDateTimeOffsetUtc() + public void Serializer_should_work_with_DateTimeOffset_utc() { SerializeAndAssert(DateTimeOffset.UtcNow); } [Fact] - public void CanSerializeDecimal() + public void Serializer_should_work_with_Decimal() { SerializeAndAssert(123m); } [Fact] - public void CanSerializeDouble() + public void Serializer_should_work_with_Double() { SerializeAndAssert(123d); } [Fact] - public void CanSerializeByte() + public void Serializer_should_work_with_Byte() { SerializeAndAssert((byte) 123); } [Fact] - public void CanSerializeSByte() + public void Serializer_should_work_with_SByte() { SerializeAndAssert((sbyte)123); } [Fact] - public void CanSerializeInt16() + public void Serializer_should_work_with_Int16() { SerializeAndAssert((short) 123); } [Fact] - public void CanSerializeInt64() + public void Serializer_should_work_with_Int64() { SerializeAndAssert(123L); } [Fact] - public void CanSerializeInt32() + public void Serializer_should_work_with_Int32() { SerializeAndAssert(123); } [Fact] - public void CanSerializeUInt16() + public void Serializer_should_work_with_UInt16() { SerializeAndAssert((ushort)123); } [Fact] - public void CanSerializeUInt64() + public void Serializer_should_work_with_UInt64() { SerializeAndAssert((ulong)123); } [Fact] - public void CanSerializeUInt32() + public void Serializer_should_work_with_UInt32() { SerializeAndAssert((uint)123); } [Fact] - public void CanSerializeLongString() + public void Serializer_should_work_with_long_String() { - var s = new string('x',1000); + var s = new string('x', 100000); SerializeAndAssert(s); } [Fact] - public void CanSerializeString() + public void Serializer_should_work_with_String() { SerializeAndAssert("hello"); } diff --git a/Hyperion.Tests/SurrogateTests.cs b/Hyperion.Tests/SurrogateTests.cs index 1fe5e6e5..57cf84d9 100644 --- a/Hyperion.Tests/SurrogateTests.cs +++ b/Hyperion.Tests/SurrogateTests.cs @@ -93,7 +93,7 @@ public KeySurrogate(string key) public class SurrogateTests { [Fact] - public void CanSerializeWithSurrogate() + public void Serializer_should_work_with_surrogates() { var surrogateHasBeenInvoked = false; var surrogates = new[] @@ -119,7 +119,7 @@ public void CanSerializeWithSurrogate() } [Fact] - public void CanSerializeWithInterfaceSurrogate() + public void Serializer_should_work_with_surrogate_interfaces() { var surrogateHasBeenInvoked = false; var surrogates = new[] @@ -145,7 +145,7 @@ public void CanSerializeWithInterfaceSurrogate() } [Fact] - public void CanSerializeWithSurrogateInCollection() + public void Serializer_should_work_with_collections_of_surrogates() { var invoked = new List(); var surrogates = new[] diff --git a/Hyperion.Tests/TestBase.cs b/Hyperion.Tests/TestBase.cs index 91480501..c1f35f99 100644 --- a/Hyperion.Tests/TestBase.cs +++ b/Hyperion.Tests/TestBase.cs @@ -14,18 +14,24 @@ namespace Hyperion.Tests { public abstract class TestBase { - private Serializer _serializer; + protected Serializer Serializer; private readonly MemoryStream _stream; + protected TestBase(SerializerOptions options) + { + Serializer = new Serializer(options); + _stream = new MemoryStream(); + } + protected TestBase() { - _serializer = new Serializer(); + Serializer = new Serializer(); _stream = new MemoryStream(); } protected void CustomInit(Serializer serializer) { - _serializer = serializer; + Serializer = serializer; } @@ -36,12 +42,22 @@ public void Reset() public void Serialize(object o) { - _serializer.Serialize(o, _stream); + Serializer.Serialize(o, _stream); + } + + public void Serialize(object o, SerializerSession session) + { + Serializer.Serialize(o, _stream, session); } public T Deserialize() { - return _serializer.Deserialize(_stream); + return Serializer.Deserialize(_stream); + } + + public T Deserialize(DeserializerSession session) + { + return Serializer.Deserialize(_stream, session); } public void AssertMemoryStreamConsumed() diff --git a/Hyperion/Attributes.cs b/Hyperion/Attributes.cs new file mode 100644 index 00000000..aefb5969 --- /dev/null +++ b/Hyperion/Attributes.cs @@ -0,0 +1,32 @@ +#region copyright +// ----------------------------------------------------------------------- +// +// Copyright (C) 2015-2016 AsynkronIT +// Copyright (C) 2016-2016 Akka.NET Team +// +// ----------------------------------------------------------------------- +#endregion + +using System; + +namespace Hyperion +{ + public abstract class HyperionAttribute : Attribute { } + + /// + /// Mark class with this attribute in order to turn preserving all of its object references + /// in scope of a single / . + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] + public sealed class PreserveReferencesAttribute : HyperionAttribute + { + public PreserveReferencesAttribute() : this(true) { } + + public PreserveReferencesAttribute(bool enabled) + { + Enabled = enabled; + } + + public bool Enabled { get; } + } +} \ No newline at end of file diff --git a/Hyperion/DefaultCodeGenerator.cs b/Hyperion/DefaultCodeGenerator.cs index 1aab89d8..1f8a1bb5 100644 --- a/Hyperion/DefaultCodeGenerator.cs +++ b/Hyperion/DefaultCodeGenerator.cs @@ -27,15 +27,15 @@ public void BuildSerializer([NotNull] Serializer serializer, [NotNull] ObjectSer { var type = objectSerializer.Type; var fields = type.GetFieldInfosForType(); + var preserveObjectReferences = objectSerializer.PreserveObjectReferences ?? serializer.Options.PreserveObjectReferences; int preallocatedBufferSize; - var writer = GetFieldsWriter(serializer, fields, out preallocatedBufferSize); - var reader = GetFieldsReader(serializer, fields, type); + var writer = GetFieldsWriter(serializer, fields, preserveObjectReferences, out preallocatedBufferSize); + var reader = GetFieldsReader(serializer, fields, type, preserveObjectReferences); objectSerializer.Initialize(reader, writer, preallocatedBufferSize); } - private ObjectReader GetFieldsReader([NotNull] Serializer serializer, [NotNull] FieldInfo[] fields, - [NotNull] Type type) + private ObjectReader GetFieldsReader([NotNull] Serializer serializer, [NotNull] FieldInfo[] fields, [NotNull] Type type, bool preserveObjectReferences) { var c = new Compiler(); var stream = c.Parameter("stream"); @@ -46,7 +46,7 @@ private ObjectReader GetFieldsReader([NotNull] Serializer serializer, [NotNull] c.Emit(assignNewObjectToTarget); - if (serializer.Options.PreserveObjectReferences) + if (preserveObjectReferences) { var trackDeserializedObjectMethod = typeof(DeserializerSession).GetTypeInfo().GetMethod(nameof(DeserializerSession.TrackDeserializedObject)); @@ -113,8 +113,7 @@ private ObjectReader GetFieldsReader([NotNull] Serializer serializer, [NotNull] return readAllFields; } - private static void EmitPreallocatedBuffer(ICompiler c, int preallocatedBufferSize, int session, - MethodInfo getBuffer) + private static void EmitPreallocatedBuffer(ICompiler c, int preallocatedBufferSize, int session, MethodInfo getBuffer) { var size = c.Constant(preallocatedBufferSize); var buffer = c.Variable(PreallocatedByteBuffer); @@ -125,17 +124,16 @@ private static void EmitPreallocatedBuffer(ICompiler c, int preallocatedBu //this generates a FieldWriter that writes all fields by unrolling all fields and calling them individually //no loops involved - private ObjectWriter GetFieldsWriter([NotNull] Serializer serializer, [NotNull] IEnumerable fields, - out int preallocatedBufferSize) + private ObjectWriter GetFieldsWriter([NotNull] Serializer serializer, [NotNull] IEnumerable fields, bool preserveObjectReferences, out int preallocatedBufferSize) { var c = new Compiler(); var stream = c.Parameter("stream"); var target = c.Parameter("target"); var session = c.Parameter("session"); - var preserveReferences = c.Constant(serializer.Options.PreserveObjectReferences); + var preserveReferences = c.Constant(preserveObjectReferences); - if (serializer.Options.PreserveObjectReferences) + if (preserveObjectReferences) { var method = typeof(SerializerSession).GetTypeInfo().GetMethod(nameof(SerializerSession.TrackSerializedObject)); diff --git a/Hyperion/Extensions/TypeEx.cs b/Hyperion/Extensions/TypeEx.cs index cfb05d3a..de6adcf8 100644 --- a/Hyperion/Extensions/TypeEx.cs +++ b/Hyperion/Extensions/TypeEx.cs @@ -100,6 +100,11 @@ public static bool IsOneDimensionalPrimitiveArray(this Type type) return type.IsArray && type.GetArrayRank() == 1 && type.GetElementType().IsHyperionPrimitive(); } + public static HyperionAttribute[] GetHyperionAttributes(this Type type) + { + return type.GetTypeInfo().GetCustomAttributes().ToArray(); + } + private static readonly ConcurrentDictionary TypeNameLookup = new ConcurrentDictionary(ByteArrayKeyComparer.Instance); diff --git a/Hyperion/ValueSerializers/ObjectSerializer.cs b/Hyperion/ValueSerializers/ObjectSerializer.cs index fe53fbfc..875e1fc7 100644 --- a/Hyperion/ValueSerializers/ObjectSerializer.cs +++ b/Hyperion/ValueSerializers/ObjectSerializer.cs @@ -29,12 +29,19 @@ public class ObjectSerializer : ValueSerializer private ObjectWriter _writer; int _preallocatedBufferSize; + public bool? PreserveObjectReferences { get; } + public ObjectSerializer(Type type) { if (type == null) throw new ArgumentNullException(nameof(type)); Type = type; + + var attributes = type.GetHyperionAttributes(); + foreach (var attribute in attributes) + if (attribute is PreserveReferencesAttribute p) PreserveObjectReferences = p.Enabled; + //TODO: remove version info var typeName = type.GetShortAssemblyQualifiedName(); // ReSharper disable once PossibleNullReferenceException