From cdfbfce2a0d83274d269667a1ee2f9ce6d7ef388 Mon Sep 17 00:00:00 2001 From: daHil Date: Sun, 24 Dec 2023 12:41:29 +0700 Subject: [PATCH 1/6] added tests for PrintingConfig --- ObjectPrinting/Tests/File.cs | 15 ++ .../Tests/ObjectPrinterAcceptanceTests.cs | 217 ++++++++++++++++-- ObjectPrinting/Tests/Student.cs | 7 + 3 files changed, 225 insertions(+), 14 deletions(-) create mode 100644 ObjectPrinting/Tests/File.cs create mode 100644 ObjectPrinting/Tests/Student.cs diff --git a/ObjectPrinting/Tests/File.cs b/ObjectPrinting/Tests/File.cs new file mode 100644 index 00000000..650dadaa --- /dev/null +++ b/ObjectPrinting/Tests/File.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace ObjectPrinting.Tests +{ + public class File + { + public string Name { get; set; } + + public Dictionary Attributes { get; set; } + + public List SimilarNames { get; set; } + + public string[] Copies { get; set; } + } +} diff --git a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs index 4c8b2445..4a6360cd 100644 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs @@ -1,27 +1,216 @@ -using NUnit.Framework; +using FluentAssertions; +using NUnit.Framework; +using ObjectPrinting.Solved; +using System.Collections.Generic; +using System.Globalization; namespace ObjectPrinting.Tests { [TestFixture] public class ObjectPrinterAcceptanceTests { + private Person _person; + + [SetUp] + public void SetUp() + { + _person = new Person { Name = "Alex", Age = 19, Height = 1.2 }; + } + + [Test] + public void PrintToString_ShouldReturnStringWithEveryObjectProperty() + { + var printer = ObjectPrinter.For(); + + string personWithEveryProperty = printer.PrintToString(_person); + + personWithEveryProperty + .Should() + .Be("Person\r\n\tId = Guid\r\n\tName = Alex\r\n\tHeight = 1,2\r\n\tAge = 19\r\n"); + } + + public void PrintToStringExcludingIntType_ShouldReturnStringWithNoIntProperty() + { + var printer = ObjectPrinter.For().Excluding(); + + string personWithNoIntProperties = printer.PrintToString(_person); + + personWithNoIntProperties.Should().Be("Person\r\n\tId = Guid\r\n\tName = Alex\r\n\tHeight = 1,2\r\n"); + } + + public void PrintToStringExcludingPropertyName_ShouldReturnStringWithNoNameProperty() + { + var printer = ObjectPrinter.For().Excluding(person => person.Name); + + string personWithNoNameProperty = printer.PrintToString(_person); + + personWithNoNameProperty.Should().Be("Person\r\n\tId = Guid\r\n\tHeight = 1,2\r\n\tAge = 19\r\n"); + } + + [Test] + public void PrintToStringUsingDoubleCultureInfo_ShouldReturnStringWithDoubleTypePropertyOfSetCulture() + { + var culture = new CultureInfo("en-US"); + var printer = ObjectPrinter.For().Printing().Using(culture); + + string personWithUSCultureForDouble = printer.PrintToString(_person); + + personWithUSCultureForDouble + .Should() + .Be("Person\r\n\tId = Guid\r\n\tName = Alex\r\n\tHeight = 1.2\r\n\tAge = 19\r\n"); + } + + [Test] + public void PrintToStringList_ShouldReturnStringWithEveryListObject() + { + var persons = new List() { new Person { Age = 1, Height = 1.2 }, new Person { Age = 5 } }; + var printer = ObjectPrinter.For(); + + string listOfPersongWithEveryItem = printer.PrintToString(persons); + + listOfPersongWithEveryItem + .Should() + .Be("Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 1,2\r\n\tAge = 1\r\n" + + "Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 5\r\n"); + } + + [Test] + public void PrintToStringArray_ShouldReturnStringWithEveryArrayObject() + { + var persons = new Person[] { new Person { Age = 1, Height = 1.2 }, new Person { Age = 5 } }; + var printer = ObjectPrinter.For(); + + string arrayOfPersonsWithEveryItem = printer.PrintToString(persons); + + arrayOfPersonsWithEveryItem + .Should() + .Be("Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 1,2\r\n\tAge = 1\r\n" + + "Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 5\r\n"); + } + + [Test] + public void PrintToStringUsingCustomIntSerialization_ShouldReturnStringWithCustomSerializationForInt() + { + var printer = ObjectPrinter.For().Printing().Using(x => (x * 2).ToString()); + + string personWithEveryIntPropertyMultByTwo = printer.PrintToString(_person); + + personWithEveryIntPropertyMultByTwo + .Should() + .Be("Person\r\n\tId = Guid\r\n\tName = Alex\r\n\tHeight = 1,2\r\n\tAge = 38\r\n"); + } + + [Test] + public void PrintToStringUsingCustomPropertySerialization_ShouldReturnStringWithCustomSerializationForNameProperty() + { + var printer = ObjectPrinter + .For() + .Printing(person => person.Name) + .Using(name => $"My name is {name}"); + + string personWithCustomNamePropertySerializer = printer.PrintToString(_person); + + personWithCustomNamePropertySerializer + .Should() + .Be("Person\r\n\tId = Guid\r\n\tName = My name is Alex\r\n\tHeight = 1,2\r\n\tAge = 19\r\n"); + } + + [Test] + public void PrintToStringTrimmingPropertySerialization_ShouldReturnStringWithTrimmedNameProperty() + { + var printer = ObjectPrinter.For() + .Printing(person => person.Name) + .TrimmedToLength(2); + + string personWithTrimmedNameProperty = printer.PrintToString(_person); + + personWithTrimmedNameProperty + .Should() + .Be("Person\r\n\tId = Guid\r\n\tName = Al\r\n\tHeight = 1,2\r\n\tAge = 19\r\n"); + } + + [Test] + public void PrintToStringObjectWithRefOnItself_ShouldReturnStringWithNoRecursedProperties() + { + var student = new Student(); + var anotherStudent = new Student() { Teacher = student }; + student.Teacher = anotherStudent; + var printer = ObjectPrinter.For(); + + string studentWithTeacherRefOnItself = printer.PrintToString(student); + + studentWithTeacherRefOnItself + .Should() + .Be("Student\r\n\tTeacher = Student\r\n\t\t" + + "Teacher = Student\r\n\t\tId = Guid\r\n\t\tName = null\r\n\t\tHeight = 0\r\n\t\tAge = 0" + + "\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 0\r\n"); + } + [Test] - public void Demo() + public void PrintToStringObjectWithDictionary_ShouldReturnStringObjectWithSerializedDictionary() { - var person = new Person { Name = "Alex", Age = 19 }; + var printer = ObjectPrinter.For(); + var file = new File() { Name = "file", Attributes = new Dictionary() { { "a", "b" } } }; + + string fileWithDictionaryProperty = printer.PrintToString(file); + + fileWithDictionaryProperty + .Should() + .Be("File\r\n\tName = file\r\n\tAttributes = \r\n\t\ta : b\r\n\tSimilarNames = null\r\n\tCopies = null\r\n"); + } + + [Test] + public void PrintToStringObjectWithList_ShouldReturnStringObjectWithSerializedList() + { + var printer = ObjectPrinter.For(); + var file = new File() + { + Name = "file", + SimilarNames = new List() { "oleg.jpg", "oleg.png" } + }; + + string fileWithListProperty = printer.PrintToString(file); + + fileWithListProperty + .Should() + .Be("File\r\n\tName = file\r\n\tAttributes = null\r\n\t" + + "SimilarNames = \r\n\t\toleg.jpg\r\n\t\toleg.png\r\n\tCopies = null\r\n"); + } + [Test] + public void PrintToStringObjectWithArray_ShouldReturnStringObjectWithSerializedList() + { + var printer = ObjectPrinter.For(); + var file = new File() + { + Name = "file", + Copies = new string[] { "oleg.jpg", "oleg.png" } + }; + + string fileWithListProperty = printer.PrintToString(file); + + fileWithListProperty + .Should() + .Be("File\r\n\tName = file\r\n\tAttributes = null\r\n\tSimilarNames = null\r\n\t" + + "Copies = \r\n\t\toleg.jpg\r\n\t\toleg.png\r\n"); + } + + [Test] + public void PrintToStringDictionaryOfObjects_ShouldReturnStringWithSerializedDictionary() + { var printer = ObjectPrinter.For(); - //1. Исключить из сериализации свойства определенного типа - //2. Указать альтернативный способ сериализации для определенного типа - //3. Для числовых типов указать культуру - //4. Настроить сериализацию конкретного свойства - //5. Настроить обрезание строковых свойств (метод должен быть виден только для строковых свойств) - //6. Исключить из сериализации конкретного свойства - - string s1 = printer.PrintToString(person); - - //7. Синтаксический сахар в виде метода расширения, сериализующего по-умолчанию - //8. ...с конфигурированием + var dict = new Dictionary() + { + {_person, "22" }, + {new Person(), "12" } + }; + + string fileWithListProperty = printer.PrintToString(dict); + + fileWithListProperty + .Should() + .Be("Person\r\n\tId = Guid\r\n\tName = Alex\r\n\tHeight = 1,2\r\n\tAge = 19\r\n : 22\r\n" + + "Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 0\r\n : 12\r\n"); } } } \ No newline at end of file diff --git a/ObjectPrinting/Tests/Student.cs b/ObjectPrinting/Tests/Student.cs new file mode 100644 index 00000000..6beb9dda --- /dev/null +++ b/ObjectPrinting/Tests/Student.cs @@ -0,0 +1,7 @@ +namespace ObjectPrinting.Tests +{ + public class Student : Person + { + public Person Teacher { get; set; } + } +} From 593adff231317fe10ceee34fbf739287e27d3895 Mon Sep 17 00:00:00 2001 From: daHil Date: Sun, 24 Dec 2023 12:43:16 +0700 Subject: [PATCH 2/6] added serializer --- ObjectPrinting/SerializationSettings.cs | 10 ++ ObjectPrinting/Serializer.cs | 143 ++++++++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 ObjectPrinting/SerializationSettings.cs create mode 100644 ObjectPrinting/Serializer.cs diff --git a/ObjectPrinting/SerializationSettings.cs b/ObjectPrinting/SerializationSettings.cs new file mode 100644 index 00000000..4aa9bcf1 --- /dev/null +++ b/ObjectPrinting/SerializationSettings.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ObjectPrinting +{ + internal class SerializationSettings + { + } +} diff --git a/ObjectPrinting/Serializer.cs b/ObjectPrinting/Serializer.cs new file mode 100644 index 00000000..26e81d40 --- /dev/null +++ b/ObjectPrinting/Serializer.cs @@ -0,0 +1,143 @@ +using System.Reflection; +using System; +using System.Text; +using System.Collections; +using System.Collections.Generic; + +namespace ObjectPrinting +{ + public class Serializer + { + private readonly SerializationSettings settings; + + public Serializer(SerializationSettings serializationSettings) + { + settings = serializationSettings; + } + + public string SerializeObject(object obj, int nestingLevel) + { + if (obj == null) + return "null"; + + var type = obj.GetType(); + if (TrySerializeCollection(obj, nestingLevel, out var collectionSerialization)) + return collectionSerialization; + + if (settings.GetSerializedObjects().Contains(obj)) + return type.Name; + + if (!type.IsValueType) + settings.AddSerializedObject(obj); + + if (TrySerializeFinalType(obj, out var typeSerialization)) + return typeSerialization; + + var identation = new string('\t', nestingLevel + 1); + var objectSerialization = new StringBuilder(); + objectSerialization.AppendLine(type.Name); + foreach (var propertyInfo in type.GetProperties()) + { + if (!TrySerializeProperty(propertyInfo, obj, nestingLevel, out var propertySerialization)) + continue; + objectSerialization.Append(identation + propertyInfo.Name + " = " + propertySerialization + Environment.NewLine); + } + + return objectSerialization.ToString(); + } + + private bool TrySerializeFinalType(object obj, out string serializedType) + { + var type = obj.GetType(); + if (settings.GetTypesSerializations().ContainsKey(type)) + { + serializedType = settings.GetTypesSerializations()[type].Invoke(obj); + + return true; + } + + if (settings.GetFinalTypes().Contains(type)) + { + serializedType = obj.ToString(); + if (settings.GetTypesWithCulture().ContainsKey(obj.GetType()) && obj is IFormattable) + serializedType = ((IFormattable)obj).ToString(null, settings.GetTypesWithCulture()[type]); + + return true; + } + + serializedType = ""; + + return false; + } + + private bool TrySerializeProperty(PropertyInfo propertyInfo, object obj, int nestingLevel, out string serializedProperty) + { + serializedProperty = ""; + if (settings.GetExcludingProperties().Contains(propertyInfo) + || settings.GetExcludingTypes().Contains(propertyInfo.PropertyType)) + return false; + + var propertyMaxLength = settings.GetPropertiesToTrim().ContainsKey(propertyInfo) ? + settings.GetPropertiesToTrim()[propertyInfo] : -1; + + serializedProperty = settings.GetPropertiesSerializations().ContainsKey(propertyInfo) ? + settings.GetPropertiesSerializations()[propertyInfo].Invoke(propertyInfo.GetValue(obj)) : + SerializeObject(propertyInfo.GetValue(obj), nestingLevel + 1).TrimEnd(); + + serializedProperty = propertyMaxLength >= 0 ? + serializedProperty[..settings.GetPropertiesToTrim()[propertyInfo]] : serializedProperty; + + return true; + } + + private bool TrySerializeCollection(object obj, int nestingLevel, out string serializedCollection) + { + serializedCollection = ""; + var type = obj.GetType(); + if (!type.IsGenericType && !type.IsArray) + return false; + + if (type.IsArray || type.GetGenericTypeDefinition() == typeof(List<>)) + { + serializedCollection = SerializeEnumerable(obj, nestingLevel); + return true; + } + + if (type.GetGenericTypeDefinition() == typeof(Dictionary<,>)) + { + serializedCollection = SerializeDictionary(obj, nestingLevel); + return true; + } + + return false; + } + + private string SerializeEnumerable(object obj, int nestingLevel) + { + var enumerable = (IEnumerable)obj; + var serializedEnumerable = new StringBuilder(); + var identation = "\r\n" + new string('\t', nestingLevel + 1); + + foreach (var item in enumerable) + serializedEnumerable.Append(identation + SerializeObject(item, nestingLevel)); + + return serializedEnumerable.ToString(); + } + + private string SerializeDictionary(object obj, int nestingLevel) + { + var dict = (IDictionary)obj; + var serializedDict = new StringBuilder(); + var identation = "\r\n" + new string('\t', nestingLevel + 1); + + foreach (var pair in dict) + { + var key = ((DictionaryEntry)pair).Key; + var value = ((DictionaryEntry)pair).Value; + serializedDict.Append(identation + SerializeObject(key, nestingLevel) + " : " + SerializeObject(value, nestingLevel)); + } + + return serializedDict.ToString(); + } + } +} From 56c06398d3d09638d0b176174c675c29921f0415 Mon Sep 17 00:00:00 2001 From: daHil Date: Sun, 24 Dec 2023 12:46:18 +0700 Subject: [PATCH 3/6] added printing config logic --- ObjectPrinting/IPrintingConfig.cs | 7 + ObjectPrinting/IPropertyPrintingConfig.cs | 11 ++ ObjectPrinting/ObjectPrinting.csproj | 2 + ObjectPrinting/PrintingConfig.cs | 122 +++++++++++++----- ObjectPrinting/PropertyPrintingConfig.cs | 44 +++++++ .../PropertyPrintingConfigExtension.cs | 15 +++ ObjectPrinting/SerializationSettings.cs | 85 +++++++++++- 7 files changed, 254 insertions(+), 32 deletions(-) create mode 100644 ObjectPrinting/IPrintingConfig.cs create mode 100644 ObjectPrinting/IPropertyPrintingConfig.cs create mode 100644 ObjectPrinting/PropertyPrintingConfig.cs create mode 100644 ObjectPrinting/PropertyPrintingConfigExtension.cs diff --git a/ObjectPrinting/IPrintingConfig.cs b/ObjectPrinting/IPrintingConfig.cs new file mode 100644 index 00000000..4b31732f --- /dev/null +++ b/ObjectPrinting/IPrintingConfig.cs @@ -0,0 +1,7 @@ +namespace ObjectPrinting +{ + public interface IPrintingConfig + { + SerializationSettings SerializationSettings { get; } + } +} diff --git a/ObjectPrinting/IPropertyPrintingConfig.cs b/ObjectPrinting/IPropertyPrintingConfig.cs new file mode 100644 index 00000000..008a9cfd --- /dev/null +++ b/ObjectPrinting/IPropertyPrintingConfig.cs @@ -0,0 +1,11 @@ +using System.Reflection; + +namespace ObjectPrinting +{ + public interface IPropertyPrintingConfig + { + PrintingConfig ParentConfig { get; } + + PropertyInfo PropertyInfo { get; } + } +} diff --git a/ObjectPrinting/ObjectPrinting.csproj b/ObjectPrinting/ObjectPrinting.csproj index 1c5eaf1c..22239d14 100644 --- a/ObjectPrinting/ObjectPrinting.csproj +++ b/ObjectPrinting/ObjectPrinting.csproj @@ -7,8 +7,10 @@ + + diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index a9e08211..beffb504 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -1,41 +1,103 @@ +using ObjectPrinting.Solved; using System; -using System.Linq; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection; using System.Text; namespace ObjectPrinting { - public class PrintingConfig + public class PrintingConfig : IPrintingConfig { + private readonly SerializationSettings _serializationSettings; + + SerializationSettings IPrintingConfig.SerializationSettings => _serializationSettings; + + public PrintingConfig() + { + _serializationSettings = new SerializationSettings(); + } + public string PrintToString(TOwner obj) { - return PrintToString(obj, 0); - } - - private string PrintToString(object obj, int nestingLevel) - { - //TODO apply configurations - if (obj == null) - return "null" + Environment.NewLine; - - var finalTypes = new[] - { - typeof(int), typeof(double), typeof(float), typeof(string), - typeof(DateTime), typeof(TimeSpan) - }; - if (finalTypes.Contains(obj.GetType())) - return obj + Environment.NewLine; - - var identation = new string('\t', nestingLevel + 1); - var sb = new StringBuilder(); - var type = obj.GetType(); - sb.AppendLine(type.Name); - foreach (var propertyInfo in type.GetProperties()) - { - sb.Append(identation + propertyInfo.Name + " = " + - PrintToString(propertyInfo.GetValue(obj), - nestingLevel + 1)); - } - return sb.ToString(); + return PrintObjectToString(obj, 0); + } + + public string PrintToString(IList lsit) + { + return PrintEnumerableToString(lsit); + } + + public string PrintToString(TOwner[] array) + { + return PrintEnumerableToString(array); + } + + public string PrintToString(Dictionary dict) + { + return PrintDictionaryToString(dict); + } + + public string PrintToString(Dictionary dict) + { + return PrintDictionaryToString(dict); + } + + public PrintingConfig Excluding() + { + _serializationSettings.AddTypeToExclude(typeof(TPropType)); + + return this; + } + + public PrintingConfig Excluding(Expression> property) + { + var memberBody = (MemberExpression)property.Body; + var propertyInfo = memberBody.Member as PropertyInfo; + _serializationSettings.AddPropertyToExclude(propertyInfo); + + return this; + } + + public PropertyPrintingConfig Printing() + { + return new PropertyPrintingConfig(this); + } + + public PropertyPrintingConfig Printing(Expression> printProperty) + { + var memberBody = (MemberExpression)printProperty.Body; + var propertyInfo = memberBody.Member as PropertyInfo; + + return new PropertyPrintingConfig(this, propertyInfo); + } + + private string PrintObjectToString(object obj, int nestingLevel) + { + _serializationSettings.GetSerializedObjects().Clear(); + var serializer = new Serializer(_serializationSettings); + + return serializer.SerializeObject(obj, nestingLevel); + } + + private string PrintEnumerableToString(IEnumerable enumerable) + { + var enumerableInString = new StringBuilder(); + + foreach (var item in enumerable) + enumerableInString.Append(PrintObjectToString(item, 0)); + + return enumerableInString.ToString(); + } + + private string PrintDictionaryToString(IDictionary dictionary) + { + var dictInString = new StringBuilder(); + + foreach (var pair in dictionary) + dictInString.AppendLine(PrintObjectToString(pair.Key, 0) + " : " + PrintObjectToString(pair.Value, 0)); + + return dictInString.ToString(); } } } \ No newline at end of file diff --git a/ObjectPrinting/PropertyPrintingConfig.cs b/ObjectPrinting/PropertyPrintingConfig.cs new file mode 100644 index 00000000..10cacc16 --- /dev/null +++ b/ObjectPrinting/PropertyPrintingConfig.cs @@ -0,0 +1,44 @@ +using System; +using System.Globalization; +using System.Reflection; + +namespace ObjectPrinting +{ + public class PropertyPrintingConfig : IPropertyPrintingConfig + { + private readonly PrintingConfig printingConfig; + private readonly PropertyInfo propertyInfo; + + public PropertyPrintingConfig(PrintingConfig printingConfig) + { + this.printingConfig = printingConfig; + } + + public PropertyPrintingConfig(PrintingConfig printingConfig, PropertyInfo propertyInfo) + { + this.printingConfig = printingConfig; + this.propertyInfo = propertyInfo; + } + + PropertyInfo IPropertyPrintingConfig.PropertyInfo => propertyInfo; + + PrintingConfig IPropertyPrintingConfig.ParentConfig => printingConfig; + + public PrintingConfig Using(CultureInfo cultureInfo) + { + ((IPrintingConfig)printingConfig).SerializationSettings.AddCultureForType(typeof(TPropType), cultureInfo); + + return printingConfig; + } + + public PrintingConfig Using(Func printProperty) + { + if (propertyInfo == null) + ((IPrintingConfig)printingConfig).SerializationSettings.AddTypeSerialization(printProperty); + else + ((IPrintingConfig)printingConfig).SerializationSettings.AddPropertySerialization(propertyInfo, printProperty); + + return printingConfig; + } + } +} diff --git a/ObjectPrinting/PropertyPrintingConfigExtension.cs b/ObjectPrinting/PropertyPrintingConfigExtension.cs new file mode 100644 index 00000000..d6b973db --- /dev/null +++ b/ObjectPrinting/PropertyPrintingConfigExtension.cs @@ -0,0 +1,15 @@ +namespace ObjectPrinting +{ + public static class PropertyPrintingConfigExtension + { + public static PrintingConfig TrimmedToLength(this PropertyPrintingConfig propConfig, int length) + { + var printingConfig = ((IPropertyPrintingConfig)propConfig).ParentConfig; + var property = ((IPropertyPrintingConfig)propConfig).PropertyInfo; + + ((IPrintingConfig)printingConfig).SerializationSettings.AddPropertyToTrim(property, length); + + return printingConfig; + } + } +} diff --git a/ObjectPrinting/SerializationSettings.cs b/ObjectPrinting/SerializationSettings.cs index 4aa9bcf1..ec9050c3 100644 --- a/ObjectPrinting/SerializationSettings.cs +++ b/ObjectPrinting/SerializationSettings.cs @@ -1,10 +1,91 @@ using System; using System.Collections.Generic; -using System.Text; +using System.Globalization; +using System.Reflection; namespace ObjectPrinting { - internal class SerializationSettings + public class SerializationSettings { + private readonly HashSet _typesToExclude; + private readonly HashSet _propertiesToExclude; + private readonly Dictionary _cultureForType; + private readonly Dictionary> _serializationForType; + private readonly Dictionary> _serializationForProperty; + private readonly Dictionary _propertiesToTrim; + private readonly HashSet _serializedObjects; + private static readonly HashSet _finalTypes = new HashSet() + { + typeof(int), typeof(uint), typeof(double), typeof(float), typeof(decimal), + typeof(long), typeof(ulong), typeof(short), typeof(ushort), + typeof(string), typeof(bool), + typeof(DateTime), typeof(TimeSpan) + + }; + + public SerializationSettings() + { + _typesToExclude = new HashSet(); + _propertiesToExclude = new HashSet(); + _cultureForType = new Dictionary(); + _serializationForType = new Dictionary>(); + _serializationForProperty = new Dictionary>(); + _propertiesToTrim = new Dictionary(); + _serializedObjects = new HashSet(); + } + + public void AddTypeToExclude(params Type[] types) + { + foreach (var type in types) + _typesToExclude.Add(type); + } + + public void AddPropertyToExclude(params PropertyInfo[] properties) + { + foreach (var property in properties) + _propertiesToExclude.Add(property); + } + + public void AddCultureForType(Type type, CultureInfo culture) + { + _cultureForType.TryAdd(type, culture); + } + + public void AddTypeSerialization(Func typeSerialization) + { + _serializationForType.TryAdd(typeof(TPropType), type => typeSerialization((TPropType)type)); + } + + public void AddPropertySerialization(PropertyInfo property, Func propertySerialization) + { + _serializationForProperty.TryAdd(property, type => propertySerialization((TPropType)type)); + } + + public void AddPropertyToTrim(PropertyInfo property, int length) + { + _propertiesToTrim.TryAdd(property, length); + } + + public void AddSerializedObject(object obj) + { + _serializedObjects.Add(obj); + } + + public HashSet GetExcludingTypes() => _typesToExclude; + + public HashSet GetExcludingProperties() => _propertiesToExclude; + + public Dictionary GetTypesWithCulture() => _cultureForType; + + public Dictionary> GetTypesSerializations() => + _serializationForType; + + public Dictionary> GetPropertiesSerializations() => + _serializationForProperty; + + public Dictionary GetPropertiesToTrim() => _propertiesToTrim; + + public HashSet GetFinalTypes() => _finalTypes; + public HashSet GetSerializedObjects() => _serializedObjects; } } From 4b029ce4a3970a0ec9943b4e42c93bdcc76e16af Mon Sep 17 00:00:00 2001 From: daHil Date: Sun, 24 Dec 2023 12:50:25 +0700 Subject: [PATCH 4/6] refactored code --- ObjectPrinting/IPrintingConfig.cs | 2 +- ObjectPrinting/IPropertyPrintingConfig.cs | 2 +- ObjectPrinting/ObjectPrinting.csproj | 22 ++--- ObjectPrinting/PrintingConfig.cs | 8 +- ObjectPrinting/PropertyPrintingConfig.cs | 8 +- .../PropertyPrintingConfigExtension.cs | 5 +- ObjectPrinting/SerializationSettings.cs | 66 ++++++++++----- ObjectPrinting/Serializer.cs | 35 ++++---- ObjectPrinting/Solved/PrintingConfig.cs | 5 +- .../Solved/PropertyPrintingConfig.cs | 4 +- .../PropertyPrintingConfigExtensions.cs | 4 +- .../Tests/ObjectPrinterAcceptanceTests.cs | 10 +-- ObjectPrinting/Tests/File.cs | 2 +- .../Tests/ObjectPrinterAcceptanceTests.cs | 81 ++++++++++--------- ObjectPrinting/Tests/Person.cs | 3 + ObjectPrinting/Tests/Student.cs | 2 +- 16 files changed, 148 insertions(+), 111 deletions(-) diff --git a/ObjectPrinting/IPrintingConfig.cs b/ObjectPrinting/IPrintingConfig.cs index 4b31732f..bb1b3c85 100644 --- a/ObjectPrinting/IPrintingConfig.cs +++ b/ObjectPrinting/IPrintingConfig.cs @@ -4,4 +4,4 @@ public interface IPrintingConfig { SerializationSettings SerializationSettings { get; } } -} +} \ No newline at end of file diff --git a/ObjectPrinting/IPropertyPrintingConfig.cs b/ObjectPrinting/IPropertyPrintingConfig.cs index 008a9cfd..89cc57e9 100644 --- a/ObjectPrinting/IPropertyPrintingConfig.cs +++ b/ObjectPrinting/IPropertyPrintingConfig.cs @@ -8,4 +8,4 @@ public interface IPropertyPrintingConfig PropertyInfo PropertyInfo { get; } } -} +} \ No newline at end of file diff --git a/ObjectPrinting/ObjectPrinting.csproj b/ObjectPrinting/ObjectPrinting.csproj index 22239d14..c3112284 100644 --- a/ObjectPrinting/ObjectPrinting.csproj +++ b/ObjectPrinting/ObjectPrinting.csproj @@ -1,16 +1,16 @@  - - 8 - netcoreapp3.1 - false - + + 8 + netcoreapp3.1 + false + - - - - - - + + + + + + diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index beffb504..2db18dd9 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -1,4 +1,3 @@ -using ObjectPrinting.Solved; using System; using System.Collections.Generic; using System.Linq.Expressions; @@ -11,13 +10,13 @@ public class PrintingConfig : IPrintingConfig { private readonly SerializationSettings _serializationSettings; - SerializationSettings IPrintingConfig.SerializationSettings => _serializationSettings; - public PrintingConfig() { _serializationSettings = new SerializationSettings(); } + SerializationSettings IPrintingConfig.SerializationSettings => _serializationSettings; + public string PrintToString(TOwner obj) { return PrintObjectToString(obj, 0); @@ -64,7 +63,8 @@ public PropertyPrintingConfig Printing() return new PropertyPrintingConfig(this); } - public PropertyPrintingConfig Printing(Expression> printProperty) + public PropertyPrintingConfig Printing( + Expression> printProperty) { var memberBody = (MemberExpression)printProperty.Body; var propertyInfo = memberBody.Member as PropertyInfo; diff --git a/ObjectPrinting/PropertyPrintingConfig.cs b/ObjectPrinting/PropertyPrintingConfig.cs index 10cacc16..58ef7bd7 100644 --- a/ObjectPrinting/PropertyPrintingConfig.cs +++ b/ObjectPrinting/PropertyPrintingConfig.cs @@ -26,7 +26,8 @@ public PropertyPrintingConfig(PrintingConfig printingConfig, PropertyInf public PrintingConfig Using(CultureInfo cultureInfo) { - ((IPrintingConfig)printingConfig).SerializationSettings.AddCultureForType(typeof(TPropType), cultureInfo); + ((IPrintingConfig)printingConfig).SerializationSettings.AddCultureForType(typeof(TPropType), + cultureInfo); return printingConfig; } @@ -36,9 +37,10 @@ public PrintingConfig Using(Func printProperty) if (propertyInfo == null) ((IPrintingConfig)printingConfig).SerializationSettings.AddTypeSerialization(printProperty); else - ((IPrintingConfig)printingConfig).SerializationSettings.AddPropertySerialization(propertyInfo, printProperty); + ((IPrintingConfig)printingConfig).SerializationSettings.AddPropertySerialization(propertyInfo, + printProperty); return printingConfig; } } -} +} \ No newline at end of file diff --git a/ObjectPrinting/PropertyPrintingConfigExtension.cs b/ObjectPrinting/PropertyPrintingConfigExtension.cs index d6b973db..6b62a55a 100644 --- a/ObjectPrinting/PropertyPrintingConfigExtension.cs +++ b/ObjectPrinting/PropertyPrintingConfigExtension.cs @@ -2,7 +2,8 @@ { public static class PropertyPrintingConfigExtension { - public static PrintingConfig TrimmedToLength(this PropertyPrintingConfig propConfig, int length) + public static PrintingConfig TrimmedToLength( + this PropertyPrintingConfig propConfig, int length) { var printingConfig = ((IPropertyPrintingConfig)propConfig).ParentConfig; var property = ((IPropertyPrintingConfig)propConfig).PropertyInfo; @@ -12,4 +13,4 @@ public static PrintingConfig TrimmedToLength(this PropertyPrinti return printingConfig; } } -} +} \ No newline at end of file diff --git a/ObjectPrinting/SerializationSettings.cs b/ObjectPrinting/SerializationSettings.cs index ec9050c3..34286111 100644 --- a/ObjectPrinting/SerializationSettings.cs +++ b/ObjectPrinting/SerializationSettings.cs @@ -7,22 +7,22 @@ namespace ObjectPrinting { public class SerializationSettings { - private readonly HashSet _typesToExclude; - private readonly HashSet _propertiesToExclude; - private readonly Dictionary _cultureForType; - private readonly Dictionary> _serializationForType; - private readonly Dictionary> _serializationForProperty; - private readonly Dictionary _propertiesToTrim; - private readonly HashSet _serializedObjects; - private static readonly HashSet _finalTypes = new HashSet() + private static readonly HashSet _finalTypes = new HashSet { typeof(int), typeof(uint), typeof(double), typeof(float), typeof(decimal), typeof(long), typeof(ulong), typeof(short), typeof(ushort), typeof(string), typeof(bool), typeof(DateTime), typeof(TimeSpan) - }; + private readonly Dictionary _cultureForType; + private readonly HashSet _propertiesToExclude; + private readonly Dictionary _propertiesToTrim; + private readonly Dictionary> _serializationForProperty; + private readonly Dictionary> _serializationForType; + private readonly HashSet _serializedObjects; + private readonly HashSet _typesToExclude; + public SerializationSettings() { _typesToExclude = new HashSet(); @@ -56,7 +56,8 @@ public void AddTypeSerialization(Func typeSerializ _serializationForType.TryAdd(typeof(TPropType), type => typeSerialization((TPropType)type)); } - public void AddPropertySerialization(PropertyInfo property, Func propertySerialization) + public void AddPropertySerialization(PropertyInfo property, + Func propertySerialization) { _serializationForProperty.TryAdd(property, type => propertySerialization((TPropType)type)); } @@ -71,21 +72,44 @@ public void AddSerializedObject(object obj) _serializedObjects.Add(obj); } - public HashSet GetExcludingTypes() => _typesToExclude; + public HashSet GetExcludingTypes() + { + return _typesToExclude; + } + + public HashSet GetExcludingProperties() + { + return _propertiesToExclude; + } - public HashSet GetExcludingProperties() => _propertiesToExclude; + public Dictionary GetTypesWithCulture() + { + return _cultureForType; + } - public Dictionary GetTypesWithCulture() => _cultureForType; + public Dictionary> GetTypesSerializations() + { + return _serializationForType; + } - public Dictionary> GetTypesSerializations() => - _serializationForType; + public Dictionary> GetPropertiesSerializations() + { + return _serializationForProperty; + } - public Dictionary> GetPropertiesSerializations() => - _serializationForProperty; + public Dictionary GetPropertiesToTrim() + { + return _propertiesToTrim; + } - public Dictionary GetPropertiesToTrim() => _propertiesToTrim; + public HashSet GetFinalTypes() + { + return _finalTypes; + } - public HashSet GetFinalTypes() => _finalTypes; - public HashSet GetSerializedObjects() => _serializedObjects; + public HashSet GetSerializedObjects() + { + return _serializedObjects; + } } -} +} \ No newline at end of file diff --git a/ObjectPrinting/Serializer.cs b/ObjectPrinting/Serializer.cs index 26e81d40..a60b9b91 100644 --- a/ObjectPrinting/Serializer.cs +++ b/ObjectPrinting/Serializer.cs @@ -1,8 +1,8 @@ -using System.Reflection; -using System; -using System.Text; +using System; using System.Collections; using System.Collections.Generic; +using System.Reflection; +using System.Text; namespace ObjectPrinting { @@ -40,7 +40,8 @@ public string SerializeObject(object obj, int nestingLevel) { if (!TrySerializeProperty(propertyInfo, obj, nestingLevel, out var propertySerialization)) continue; - objectSerialization.Append(identation + propertyInfo.Name + " = " + propertySerialization + Environment.NewLine); + objectSerialization.Append(identation + propertyInfo.Name + " = " + propertySerialization + + Environment.NewLine); } return objectSerialization.ToString(); @@ -70,22 +71,25 @@ private bool TrySerializeFinalType(object obj, out string serializedType) return false; } - private bool TrySerializeProperty(PropertyInfo propertyInfo, object obj, int nestingLevel, out string serializedProperty) + private bool TrySerializeProperty(PropertyInfo propertyInfo, object obj, int nestingLevel, + out string serializedProperty) { serializedProperty = ""; if (settings.GetExcludingProperties().Contains(propertyInfo) || settings.GetExcludingTypes().Contains(propertyInfo.PropertyType)) return false; - var propertyMaxLength = settings.GetPropertiesToTrim().ContainsKey(propertyInfo) ? - settings.GetPropertiesToTrim()[propertyInfo] : -1; + var propertyMaxLength = settings.GetPropertiesToTrim().ContainsKey(propertyInfo) + ? settings.GetPropertiesToTrim()[propertyInfo] + : -1; - serializedProperty = settings.GetPropertiesSerializations().ContainsKey(propertyInfo) ? - settings.GetPropertiesSerializations()[propertyInfo].Invoke(propertyInfo.GetValue(obj)) : - SerializeObject(propertyInfo.GetValue(obj), nestingLevel + 1).TrimEnd(); + serializedProperty = settings.GetPropertiesSerializations().ContainsKey(propertyInfo) + ? settings.GetPropertiesSerializations()[propertyInfo].Invoke(propertyInfo.GetValue(obj)) + : SerializeObject(propertyInfo.GetValue(obj), nestingLevel + 1).TrimEnd(); - serializedProperty = propertyMaxLength >= 0 ? - serializedProperty[..settings.GetPropertiesToTrim()[propertyInfo]] : serializedProperty; + serializedProperty = propertyMaxLength >= 0 + ? serializedProperty[..settings.GetPropertiesToTrim()[propertyInfo]] + : serializedProperty; return true; } @@ -100,12 +104,14 @@ private bool TrySerializeCollection(object obj, int nestingLevel, out string ser if (type.IsArray || type.GetGenericTypeDefinition() == typeof(List<>)) { serializedCollection = SerializeEnumerable(obj, nestingLevel); + return true; } if (type.GetGenericTypeDefinition() == typeof(Dictionary<,>)) { serializedCollection = SerializeDictionary(obj, nestingLevel); + return true; } @@ -134,10 +140,11 @@ private string SerializeDictionary(object obj, int nestingLevel) { var key = ((DictionaryEntry)pair).Key; var value = ((DictionaryEntry)pair).Value; - serializedDict.Append(identation + SerializeObject(key, nestingLevel) + " : " + SerializeObject(value, nestingLevel)); + serializedDict.Append(identation + SerializeObject(key, nestingLevel) + " : " + + SerializeObject(value, nestingLevel)); } return serializedDict.ToString(); } } -} +} \ No newline at end of file diff --git a/ObjectPrinting/Solved/PrintingConfig.cs b/ObjectPrinting/Solved/PrintingConfig.cs index 0ec5aeb2..f52c669a 100644 --- a/ObjectPrinting/Solved/PrintingConfig.cs +++ b/ObjectPrinting/Solved/PrintingConfig.cs @@ -12,7 +12,8 @@ public PropertyPrintingConfig Printing() return new PropertyPrintingConfig(this); } - public PropertyPrintingConfig Printing(Expression> memberSelector) + public PropertyPrintingConfig Printing( + Expression> memberSelector) { return new PropertyPrintingConfig(this); } @@ -51,11 +52,9 @@ private string PrintToString(object obj, int nestingLevel) var type = obj.GetType(); sb.AppendLine(type.Name); foreach (var propertyInfo in type.GetProperties()) - { sb.Append(identation + propertyInfo.Name + " = " + PrintToString(propertyInfo.GetValue(obj), nestingLevel + 1)); - } return sb.ToString(); } } diff --git a/ObjectPrinting/Solved/PropertyPrintingConfig.cs b/ObjectPrinting/Solved/PropertyPrintingConfig.cs index a509697d..8cbfbf08 100644 --- a/ObjectPrinting/Solved/PropertyPrintingConfig.cs +++ b/ObjectPrinting/Solved/PropertyPrintingConfig.cs @@ -12,6 +12,8 @@ public PropertyPrintingConfig(PrintingConfig printingConfig) this.printingConfig = printingConfig; } + PrintingConfig IPropertyPrintingConfig.ParentConfig => printingConfig; + public PrintingConfig Using(Func print) { return printingConfig; @@ -21,8 +23,6 @@ public PrintingConfig Using(CultureInfo culture) { return printingConfig; } - - PrintingConfig IPropertyPrintingConfig.ParentConfig => printingConfig; } public interface IPropertyPrintingConfig diff --git a/ObjectPrinting/Solved/PropertyPrintingConfigExtensions.cs b/ObjectPrinting/Solved/PropertyPrintingConfigExtensions.cs index dd392239..61710607 100644 --- a/ObjectPrinting/Solved/PropertyPrintingConfigExtensions.cs +++ b/ObjectPrinting/Solved/PropertyPrintingConfigExtensions.cs @@ -9,10 +9,10 @@ public static string PrintToString(this T obj, Func, Printi return config(ObjectPrinter.For()).PrintToString(obj); } - public static PrintingConfig TrimmedToLength(this PropertyPrintingConfig propConfig, int maxLen) + public static PrintingConfig TrimmedToLength( + this PropertyPrintingConfig propConfig, int maxLen) { return ((IPropertyPrintingConfig)propConfig).ParentConfig; } - } } \ No newline at end of file diff --git a/ObjectPrinting/Solved/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrinting/Solved/Tests/ObjectPrinterAcceptanceTests.cs index ac52d5ee..9582fd84 100644 --- a/ObjectPrinting/Solved/Tests/ObjectPrinterAcceptanceTests.cs +++ b/ObjectPrinting/Solved/Tests/ObjectPrinterAcceptanceTests.cs @@ -25,13 +25,13 @@ public void Demo() //6. Исключить из сериализации конкретного свойства .Excluding(p => p.Age); - string s1 = printer.PrintToString(person); - + var s1 = printer.PrintToString(person); + //7. Синтаксический сахар в виде метода расширения, сериализующего по-умолчанию - string s2 = person.PrintToString(); - + var s2 = person.PrintToString(); + //8. ...с конфигурированием - string s3 = person.PrintToString(s => s.Excluding(p => p.Age)); + var s3 = person.PrintToString(s => s.Excluding(p => p.Age)); Console.WriteLine(s1); Console.WriteLine(s2); Console.WriteLine(s3); diff --git a/ObjectPrinting/Tests/File.cs b/ObjectPrinting/Tests/File.cs index 650dadaa..f9f87216 100644 --- a/ObjectPrinting/Tests/File.cs +++ b/ObjectPrinting/Tests/File.cs @@ -12,4 +12,4 @@ public class File public string[] Copies { get; set; } } -} +} \ No newline at end of file diff --git a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs index 4a6360cd..7915c0dd 100644 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs @@ -1,28 +1,27 @@ -using FluentAssertions; -using NUnit.Framework; -using ObjectPrinting.Solved; -using System.Collections.Generic; +using System.Collections.Generic; using System.Globalization; +using FluentAssertions; +using NUnit.Framework; namespace ObjectPrinting.Tests { [TestFixture] public class ObjectPrinterAcceptanceTests { - private Person _person; - [SetUp] public void SetUp() { _person = new Person { Name = "Alex", Age = 19, Height = 1.2 }; } + private Person _person; + [Test] public void PrintToString_ShouldReturnStringWithEveryObjectProperty() { var printer = ObjectPrinter.For(); - string personWithEveryProperty = printer.PrintToString(_person); + var personWithEveryProperty = printer.PrintToString(_person); personWithEveryProperty .Should() @@ -33,7 +32,7 @@ public void PrintToStringExcludingIntType_ShouldReturnStringWithNoIntProperty() { var printer = ObjectPrinter.For().Excluding(); - string personWithNoIntProperties = printer.PrintToString(_person); + var personWithNoIntProperties = printer.PrintToString(_person); personWithNoIntProperties.Should().Be("Person\r\n\tId = Guid\r\n\tName = Alex\r\n\tHeight = 1,2\r\n"); } @@ -42,7 +41,7 @@ public void PrintToStringExcludingPropertyName_ShouldReturnStringWithNoNamePrope { var printer = ObjectPrinter.For().Excluding(person => person.Name); - string personWithNoNameProperty = printer.PrintToString(_person); + var personWithNoNameProperty = printer.PrintToString(_person); personWithNoNameProperty.Should().Be("Person\r\n\tId = Guid\r\n\tHeight = 1,2\r\n\tAge = 19\r\n"); } @@ -53,7 +52,7 @@ public void PrintToStringUsingDoubleCultureInfo_ShouldReturnStringWithDoubleType var culture = new CultureInfo("en-US"); var printer = ObjectPrinter.For().Printing().Using(culture); - string personWithUSCultureForDouble = printer.PrintToString(_person); + var personWithUSCultureForDouble = printer.PrintToString(_person); personWithUSCultureForDouble .Should() @@ -63,29 +62,29 @@ public void PrintToStringUsingDoubleCultureInfo_ShouldReturnStringWithDoubleType [Test] public void PrintToStringList_ShouldReturnStringWithEveryListObject() { - var persons = new List() { new Person { Age = 1, Height = 1.2 }, new Person { Age = 5 } }; + var persons = new List { new Person { Age = 1, Height = 1.2 }, new Person { Age = 5 } }; var printer = ObjectPrinter.For(); - string listOfPersongWithEveryItem = printer.PrintToString(persons); + var listOfPersongWithEveryItem = printer.PrintToString(persons); listOfPersongWithEveryItem .Should() .Be("Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 1,2\r\n\tAge = 1\r\n" + - "Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 5\r\n"); + "Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 5\r\n"); } [Test] public void PrintToStringArray_ShouldReturnStringWithEveryArrayObject() { - var persons = new Person[] { new Person { Age = 1, Height = 1.2 }, new Person { Age = 5 } }; + var persons = new[] { new Person { Age = 1, Height = 1.2 }, new Person { Age = 5 } }; var printer = ObjectPrinter.For(); - string arrayOfPersonsWithEveryItem = printer.PrintToString(persons); + var arrayOfPersonsWithEveryItem = printer.PrintToString(persons); arrayOfPersonsWithEveryItem .Should() .Be("Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 1,2\r\n\tAge = 1\r\n" + - "Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 5\r\n"); + "Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 5\r\n"); } [Test] @@ -93,7 +92,7 @@ public void PrintToStringUsingCustomIntSerialization_ShouldReturnStringWithCusto { var printer = ObjectPrinter.For().Printing().Using(x => (x * 2).ToString()); - string personWithEveryIntPropertyMultByTwo = printer.PrintToString(_person); + var personWithEveryIntPropertyMultByTwo = printer.PrintToString(_person); personWithEveryIntPropertyMultByTwo .Should() @@ -101,14 +100,15 @@ public void PrintToStringUsingCustomIntSerialization_ShouldReturnStringWithCusto } [Test] - public void PrintToStringUsingCustomPropertySerialization_ShouldReturnStringWithCustomSerializationForNameProperty() + public void + PrintToStringUsingCustomPropertySerialization_ShouldReturnStringWithCustomSerializationForNameProperty() { var printer = ObjectPrinter .For() .Printing(person => person.Name) .Using(name => $"My name is {name}"); - string personWithCustomNamePropertySerializer = printer.PrintToString(_person); + var personWithCustomNamePropertySerializer = printer.PrintToString(_person); personWithCustomNamePropertySerializer .Should() @@ -122,7 +122,7 @@ public void PrintToStringTrimmingPropertySerialization_ShouldReturnStringWithTri .Printing(person => person.Name) .TrimmedToLength(2); - string personWithTrimmedNameProperty = printer.PrintToString(_person); + var personWithTrimmedNameProperty = printer.PrintToString(_person); personWithTrimmedNameProperty .Should() @@ -133,84 +133,85 @@ public void PrintToStringTrimmingPropertySerialization_ShouldReturnStringWithTri public void PrintToStringObjectWithRefOnItself_ShouldReturnStringWithNoRecursedProperties() { var student = new Student(); - var anotherStudent = new Student() { Teacher = student }; + var anotherStudent = new Student { Teacher = student }; student.Teacher = anotherStudent; var printer = ObjectPrinter.For(); - string studentWithTeacherRefOnItself = printer.PrintToString(student); + var studentWithTeacherRefOnItself = printer.PrintToString(student); studentWithTeacherRefOnItself .Should() .Be("Student\r\n\tTeacher = Student\r\n\t\t" - + "Teacher = Student\r\n\t\tId = Guid\r\n\t\tName = null\r\n\t\tHeight = 0\r\n\t\tAge = 0" - + "\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 0\r\n"); + + "Teacher = Student\r\n\t\tId = Guid\r\n\t\tName = null\r\n\t\tHeight = 0\r\n\t\tAge = 0" + + "\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 0\r\n"); } [Test] public void PrintToStringObjectWithDictionary_ShouldReturnStringObjectWithSerializedDictionary() { var printer = ObjectPrinter.For(); - var file = new File() { Name = "file", Attributes = new Dictionary() { { "a", "b" } } }; + var file = new File { Name = "file", Attributes = new Dictionary { { "a", "b" } } }; - string fileWithDictionaryProperty = printer.PrintToString(file); + var fileWithDictionaryProperty = printer.PrintToString(file); fileWithDictionaryProperty .Should() - .Be("File\r\n\tName = file\r\n\tAttributes = \r\n\t\ta : b\r\n\tSimilarNames = null\r\n\tCopies = null\r\n"); + .Be( + "File\r\n\tName = file\r\n\tAttributes = \r\n\t\ta : b\r\n\tSimilarNames = null\r\n\tCopies = null\r\n"); } [Test] public void PrintToStringObjectWithList_ShouldReturnStringObjectWithSerializedList() { var printer = ObjectPrinter.For(); - var file = new File() + var file = new File { Name = "file", - SimilarNames = new List() { "oleg.jpg", "oleg.png" } + SimilarNames = new List { "oleg.jpg", "oleg.png" } }; - string fileWithListProperty = printer.PrintToString(file); + var fileWithListProperty = printer.PrintToString(file); fileWithListProperty .Should() .Be("File\r\n\tName = file\r\n\tAttributes = null\r\n\t" - + "SimilarNames = \r\n\t\toleg.jpg\r\n\t\toleg.png\r\n\tCopies = null\r\n"); + + "SimilarNames = \r\n\t\toleg.jpg\r\n\t\toleg.png\r\n\tCopies = null\r\n"); } [Test] public void PrintToStringObjectWithArray_ShouldReturnStringObjectWithSerializedList() { var printer = ObjectPrinter.For(); - var file = new File() + var file = new File { Name = "file", - Copies = new string[] { "oleg.jpg", "oleg.png" } + Copies = new[] { "oleg.jpg", "oleg.png" } }; - string fileWithListProperty = printer.PrintToString(file); + var fileWithListProperty = printer.PrintToString(file); fileWithListProperty .Should() .Be("File\r\n\tName = file\r\n\tAttributes = null\r\n\tSimilarNames = null\r\n\t" - + "Copies = \r\n\t\toleg.jpg\r\n\t\toleg.png\r\n"); + + "Copies = \r\n\t\toleg.jpg\r\n\t\toleg.png\r\n"); } [Test] public void PrintToStringDictionaryOfObjects_ShouldReturnStringWithSerializedDictionary() { var printer = ObjectPrinter.For(); - var dict = new Dictionary() + var dict = new Dictionary { - {_person, "22" }, - {new Person(), "12" } + { _person, "22" }, + { new Person(), "12" } }; - string fileWithListProperty = printer.PrintToString(dict); + var fileWithListProperty = printer.PrintToString(dict); fileWithListProperty .Should() .Be("Person\r\n\tId = Guid\r\n\tName = Alex\r\n\tHeight = 1,2\r\n\tAge = 19\r\n : 22\r\n" - + "Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 0\r\n : 12\r\n"); + + "Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 0\r\n : 12\r\n"); } } } \ No newline at end of file diff --git a/ObjectPrinting/Tests/Person.cs b/ObjectPrinting/Tests/Person.cs index f9555955..9cee17de 100644 --- a/ObjectPrinting/Tests/Person.cs +++ b/ObjectPrinting/Tests/Person.cs @@ -5,8 +5,11 @@ namespace ObjectPrinting.Tests public class Person { public Guid Id { get; set; } + public string Name { get; set; } + public double Height { get; set; } + public int Age { get; set; } } } \ No newline at end of file diff --git a/ObjectPrinting/Tests/Student.cs b/ObjectPrinting/Tests/Student.cs index 6beb9dda..cbac7a8b 100644 --- a/ObjectPrinting/Tests/Student.cs +++ b/ObjectPrinting/Tests/Student.cs @@ -4,4 +4,4 @@ public class Student : Person { public Person Teacher { get; set; } } -} +} \ No newline at end of file From 2a7369f4dda6ed4c33bfaee2487ff7be32c31943 Mon Sep 17 00:00:00 2001 From: daHil Date: Wed, 27 Dec 2023 01:52:10 +0700 Subject: [PATCH 5/6] refactored --- ObjectPrinting/IPrintingConfig.cs | 7 - ObjectPrinting/IPropertyPrintingConfig.cs | 11 - ObjectPrinting/ObjectPrinting.csproj | 4 +- ObjectPrinting/PrintingConfig.cs | 167 ++++++--- ObjectPrinting/PropertyPrintingConfig.cs | 38 +- .../PropertyPrintingConfigExtension.cs | 16 - ObjectPrinting/SerializationSettings.cs | 115 ------ ObjectPrinting/Serializer.cs | 150 -------- ObjectPrinting/Tests/File.cs | 1 + .../Tests/ObjectPrinterAcceptanceTests.cs | 213 +---------- ObjectPrinting/Tests/ObjectPrinterTests.cs | 344 ++++++++++++++++++ ObjectPrinting/Tests/Student.cs | 2 + ObjectPrinting/TypePrintingConfig.cs | 26 ++ 13 files changed, 522 insertions(+), 572 deletions(-) delete mode 100644 ObjectPrinting/IPrintingConfig.cs delete mode 100644 ObjectPrinting/IPropertyPrintingConfig.cs delete mode 100644 ObjectPrinting/PropertyPrintingConfigExtension.cs delete mode 100644 ObjectPrinting/SerializationSettings.cs delete mode 100644 ObjectPrinting/Serializer.cs create mode 100644 ObjectPrinting/Tests/ObjectPrinterTests.cs create mode 100644 ObjectPrinting/TypePrintingConfig.cs diff --git a/ObjectPrinting/IPrintingConfig.cs b/ObjectPrinting/IPrintingConfig.cs deleted file mode 100644 index bb1b3c85..00000000 --- a/ObjectPrinting/IPrintingConfig.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ObjectPrinting -{ - public interface IPrintingConfig - { - SerializationSettings SerializationSettings { get; } - } -} \ No newline at end of file diff --git a/ObjectPrinting/IPropertyPrintingConfig.cs b/ObjectPrinting/IPropertyPrintingConfig.cs deleted file mode 100644 index 89cc57e9..00000000 --- a/ObjectPrinting/IPropertyPrintingConfig.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Reflection; - -namespace ObjectPrinting -{ - public interface IPropertyPrintingConfig - { - PrintingConfig ParentConfig { get; } - - PropertyInfo PropertyInfo { get; } - } -} \ No newline at end of file diff --git a/ObjectPrinting/ObjectPrinting.csproj b/ObjectPrinting/ObjectPrinting.csproj index c3112284..730c9586 100644 --- a/ObjectPrinting/ObjectPrinting.csproj +++ b/ObjectPrinting/ObjectPrinting.csproj @@ -1,8 +1,8 @@  - 8 - netcoreapp3.1 + 9.0 + net8.0 false diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 2db18dd9..40af3a6c 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -1,103 +1,184 @@ using System; +using System.Collections; using System.Collections.Generic; +using System.Collections.Immutable; +using System.Globalization; +using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; namespace ObjectPrinting { - public class PrintingConfig : IPrintingConfig + public class PrintingConfig { - private readonly SerializationSettings _serializationSettings; + private static readonly HashSet _finalTypes = new() + { + typeof(int), typeof(uint), typeof(double), typeof(float), typeof(decimal), + typeof(long), typeof(ulong), typeof(short), typeof(ushort), + typeof(string), typeof(bool), + typeof(DateTime), typeof(TimeSpan), typeof(Guid) + }; + + private readonly HashSet excludedProperties = new(); + private readonly HashSet excludedTypes = new(); + protected readonly Dictionary propertiesMaxLength = new(); + protected readonly Dictionary> propertiesSerialization = new(); + protected readonly Dictionary typesCulture = new(); + protected readonly Dictionary> typesSerialization = new(); + private Func recursivePropertiesSerialization; public PrintingConfig() { - _serializationSettings = new SerializationSettings(); } - SerializationSettings IPrintingConfig.SerializationSettings => _serializationSettings; + protected PrintingConfig(PrintingConfig config) + { + typesCulture = config.typesCulture; + propertiesMaxLength = config.propertiesMaxLength; + propertiesSerialization = config.propertiesSerialization; + typesSerialization = config.typesSerialization; + } public string PrintToString(TOwner obj) { - return PrintObjectToString(obj, 0); + return SerializeObject(obj, ImmutableList.Empty); } - public string PrintToString(IList lsit) + public PrintingConfig Excluding() { - return PrintEnumerableToString(lsit); + excludedTypes.Add(typeof(TPropType)); + + return this; } - public string PrintToString(TOwner[] array) + public PrintingConfig Excluding(Expression> property) { - return PrintEnumerableToString(array); + var memberBody = (MemberExpression)property.Body; + var propertyInfo = memberBody.Member; + + excludedProperties.Add(propertyInfo); + + return this; } - public string PrintToString(Dictionary dict) + public TypePrintingConfig Printing() { - return PrintDictionaryToString(dict); + return new TypePrintingConfig(this); } - public string PrintToString(Dictionary dict) + public PropertyPrintingConfig Printing( + Expression> printProperty) { - return PrintDictionaryToString(dict); + var memberBody = (MemberExpression)printProperty.Body; + var propertyInfo = memberBody.Member; + + return new PropertyPrintingConfig(this, propertyInfo); } - public PrintingConfig Excluding() + public PrintingConfig PrintRecursion(Exception exception) { - _serializationSettings.AddTypeToExclude(typeof(TPropType)); + recursivePropertiesSerialization = () => throw exception; return this; } - public PrintingConfig Excluding(Expression> property) + public PrintingConfig PrintRecursion(Func printProperty) { - var memberBody = (MemberExpression)property.Body; - var propertyInfo = memberBody.Member as PropertyInfo; - _serializationSettings.AddPropertyToExclude(propertyInfo); + recursivePropertiesSerialization = printProperty; return this; } - public PropertyPrintingConfig Printing() + private string SerializeObject(object obj, IImmutableList previousObjects) { - return new PropertyPrintingConfig(this); + if (obj == null) + return "null"; + + var type = obj.GetType(); + if (previousObjects.Any(prev => prev == obj)) + { + if (recursivePropertiesSerialization != null) + return recursivePropertiesSerialization(); + return "Recursive property"; + } + + + if (obj is IEnumerable && obj is not string) + return SerializeEnumerable(obj, previousObjects); + + if (_finalTypes.Contains(type)) + return SerializeFinalType(obj); + + var identation = new string('\t', previousObjects.Count + 1); + previousObjects = previousObjects.Add(obj); + var objectSerialization = new StringBuilder(); + objectSerialization.AppendLine(type.Name); + var members = Array.Empty().Concat(type.GetProperties()).Concat(type.GetFields()); + foreach (var memberInfo in members) + { + var memberType = memberInfo.MemberType == MemberTypes.Property + ? (memberInfo as PropertyInfo).PropertyType + : (memberInfo as FieldInfo).FieldType; + if (excludedProperties.Contains(memberInfo) + || excludedTypes.Contains(memberType)) + continue; + + objectSerialization.Append(identation); + objectSerialization.Append(memberInfo.Name); + objectSerialization.Append(" = "); + objectSerialization.Append(SerializeMember(memberInfo, obj, previousObjects)); + objectSerialization.Append(Environment.NewLine); + } + + return objectSerialization.ToString(); } - public PropertyPrintingConfig Printing( - Expression> printProperty) + private string SerializeFinalType(object obj) { - var memberBody = (MemberExpression)printProperty.Body; - var propertyInfo = memberBody.Member as PropertyInfo; + var type = obj.GetType(); + if (typesSerialization.TryGetValue(type, out var serialization)) + return serialization.Invoke(obj); - return new PropertyPrintingConfig(this, propertyInfo); - } - - private string PrintObjectToString(object obj, int nestingLevel) - { - _serializationSettings.GetSerializedObjects().Clear(); - var serializer = new Serializer(_serializationSettings); + var result = obj.ToString(); + if (typesCulture.ContainsKey(obj.GetType())) + result = ((IFormattable)obj).ToString(null, typesCulture[type]); - return serializer.SerializeObject(obj, nestingLevel); + return result; } - private string PrintEnumerableToString(IEnumerable enumerable) + private string SerializeMember(MemberInfo memberInfo, object obj, IImmutableList previousObjects) { - var enumerableInString = new StringBuilder(); + var value = memberInfo.MemberType == MemberTypes.Property + ? (memberInfo as PropertyInfo).GetValue(obj) + : (memberInfo as FieldInfo).GetValue(obj); + var serializedProperty = propertiesSerialization.TryGetValue(memberInfo, out var serialization) + ? serialization.Invoke(value) + : SerializeObject(value, previousObjects).TrimEnd(); - foreach (var item in enumerable) - enumerableInString.Append(PrintObjectToString(item, 0)); + var propertyMaxLength = propertiesMaxLength.TryGetValue(memberInfo, out var length) + ? length + : serializedProperty.Length; + + serializedProperty = serializedProperty[..propertyMaxLength]; - return enumerableInString.ToString(); + return serializedProperty; } - private string PrintDictionaryToString(IDictionary dictionary) + private string SerializeEnumerable(object obj, IImmutableList previousObjects) { - var dictInString = new StringBuilder(); + var enumerable = (IEnumerable)obj; + var serializedEnumerable = new StringBuilder(); + var nestingLevel = previousObjects.Count == 0 ? 0 : previousObjects.Count + 1; + var identation = nestingLevel == 0 ? "" : Environment.NewLine + new string('\t', nestingLevel); - foreach (var pair in dictionary) - dictInString.AppendLine(PrintObjectToString(pair.Key, 0) + " : " + PrintObjectToString(pair.Value, 0)); + foreach (var item in enumerable) + { + serializedEnumerable.Append(identation); + serializedEnumerable.Append(SerializeObject(item, previousObjects)); + } - return dictInString.ToString(); + return serializedEnumerable.ToString(); } } } \ No newline at end of file diff --git a/ObjectPrinting/PropertyPrintingConfig.cs b/ObjectPrinting/PropertyPrintingConfig.cs index 58ef7bd7..e5108b47 100644 --- a/ObjectPrinting/PropertyPrintingConfig.cs +++ b/ObjectPrinting/PropertyPrintingConfig.cs @@ -1,46 +1,32 @@ using System; -using System.Globalization; using System.Reflection; namespace ObjectPrinting { - public class PropertyPrintingConfig : IPropertyPrintingConfig + public class PropertyPrintingConfig : PrintingConfig { - private readonly PrintingConfig printingConfig; - private readonly PropertyInfo propertyInfo; + private readonly MemberInfo propertyInfo; - public PropertyPrintingConfig(PrintingConfig printingConfig) + public PropertyPrintingConfig(PrintingConfig config, MemberInfo propertyInfo) : base(config) { - this.printingConfig = printingConfig; - } - - public PropertyPrintingConfig(PrintingConfig printingConfig, PropertyInfo propertyInfo) - { - this.printingConfig = printingConfig; this.propertyInfo = propertyInfo; } - PropertyInfo IPropertyPrintingConfig.PropertyInfo => propertyInfo; - - PrintingConfig IPropertyPrintingConfig.ParentConfig => printingConfig; - - public PrintingConfig Using(CultureInfo cultureInfo) + public PropertyPrintingConfig Using(Func printProperty) { - ((IPrintingConfig)printingConfig).SerializationSettings.AddCultureForType(typeof(TPropType), - cultureInfo); + propertiesSerialization.TryAdd(propertyInfo, type => printProperty((TPropType)type)); - return printingConfig; + return this; } - public PrintingConfig Using(Func printProperty) + public PropertyPrintingConfig TrimToLength(int length) { - if (propertyInfo == null) - ((IPrintingConfig)printingConfig).SerializationSettings.AddTypeSerialization(printProperty); - else - ((IPrintingConfig)printingConfig).SerializationSettings.AddPropertySerialization(propertyInfo, - printProperty); + if (length < 0) + throw new ArgumentException("length can not be negative"); + + propertiesMaxLength.Add(propertyInfo, length); - return printingConfig; + return this; } } } \ No newline at end of file diff --git a/ObjectPrinting/PropertyPrintingConfigExtension.cs b/ObjectPrinting/PropertyPrintingConfigExtension.cs deleted file mode 100644 index 6b62a55a..00000000 --- a/ObjectPrinting/PropertyPrintingConfigExtension.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace ObjectPrinting -{ - public static class PropertyPrintingConfigExtension - { - public static PrintingConfig TrimmedToLength( - this PropertyPrintingConfig propConfig, int length) - { - var printingConfig = ((IPropertyPrintingConfig)propConfig).ParentConfig; - var property = ((IPropertyPrintingConfig)propConfig).PropertyInfo; - - ((IPrintingConfig)printingConfig).SerializationSettings.AddPropertyToTrim(property, length); - - return printingConfig; - } - } -} \ No newline at end of file diff --git a/ObjectPrinting/SerializationSettings.cs b/ObjectPrinting/SerializationSettings.cs deleted file mode 100644 index 34286111..00000000 --- a/ObjectPrinting/SerializationSettings.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Reflection; - -namespace ObjectPrinting -{ - public class SerializationSettings - { - private static readonly HashSet _finalTypes = new HashSet - { - typeof(int), typeof(uint), typeof(double), typeof(float), typeof(decimal), - typeof(long), typeof(ulong), typeof(short), typeof(ushort), - typeof(string), typeof(bool), - typeof(DateTime), typeof(TimeSpan) - }; - - private readonly Dictionary _cultureForType; - private readonly HashSet _propertiesToExclude; - private readonly Dictionary _propertiesToTrim; - private readonly Dictionary> _serializationForProperty; - private readonly Dictionary> _serializationForType; - private readonly HashSet _serializedObjects; - private readonly HashSet _typesToExclude; - - public SerializationSettings() - { - _typesToExclude = new HashSet(); - _propertiesToExclude = new HashSet(); - _cultureForType = new Dictionary(); - _serializationForType = new Dictionary>(); - _serializationForProperty = new Dictionary>(); - _propertiesToTrim = new Dictionary(); - _serializedObjects = new HashSet(); - } - - public void AddTypeToExclude(params Type[] types) - { - foreach (var type in types) - _typesToExclude.Add(type); - } - - public void AddPropertyToExclude(params PropertyInfo[] properties) - { - foreach (var property in properties) - _propertiesToExclude.Add(property); - } - - public void AddCultureForType(Type type, CultureInfo culture) - { - _cultureForType.TryAdd(type, culture); - } - - public void AddTypeSerialization(Func typeSerialization) - { - _serializationForType.TryAdd(typeof(TPropType), type => typeSerialization((TPropType)type)); - } - - public void AddPropertySerialization(PropertyInfo property, - Func propertySerialization) - { - _serializationForProperty.TryAdd(property, type => propertySerialization((TPropType)type)); - } - - public void AddPropertyToTrim(PropertyInfo property, int length) - { - _propertiesToTrim.TryAdd(property, length); - } - - public void AddSerializedObject(object obj) - { - _serializedObjects.Add(obj); - } - - public HashSet GetExcludingTypes() - { - return _typesToExclude; - } - - public HashSet GetExcludingProperties() - { - return _propertiesToExclude; - } - - public Dictionary GetTypesWithCulture() - { - return _cultureForType; - } - - public Dictionary> GetTypesSerializations() - { - return _serializationForType; - } - - public Dictionary> GetPropertiesSerializations() - { - return _serializationForProperty; - } - - public Dictionary GetPropertiesToTrim() - { - return _propertiesToTrim; - } - - public HashSet GetFinalTypes() - { - return _finalTypes; - } - - public HashSet GetSerializedObjects() - { - return _serializedObjects; - } - } -} \ No newline at end of file diff --git a/ObjectPrinting/Serializer.cs b/ObjectPrinting/Serializer.cs deleted file mode 100644 index a60b9b91..00000000 --- a/ObjectPrinting/Serializer.cs +++ /dev/null @@ -1,150 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Text; - -namespace ObjectPrinting -{ - public class Serializer - { - private readonly SerializationSettings settings; - - public Serializer(SerializationSettings serializationSettings) - { - settings = serializationSettings; - } - - public string SerializeObject(object obj, int nestingLevel) - { - if (obj == null) - return "null"; - - var type = obj.GetType(); - if (TrySerializeCollection(obj, nestingLevel, out var collectionSerialization)) - return collectionSerialization; - - if (settings.GetSerializedObjects().Contains(obj)) - return type.Name; - - if (!type.IsValueType) - settings.AddSerializedObject(obj); - - if (TrySerializeFinalType(obj, out var typeSerialization)) - return typeSerialization; - - var identation = new string('\t', nestingLevel + 1); - var objectSerialization = new StringBuilder(); - objectSerialization.AppendLine(type.Name); - foreach (var propertyInfo in type.GetProperties()) - { - if (!TrySerializeProperty(propertyInfo, obj, nestingLevel, out var propertySerialization)) - continue; - objectSerialization.Append(identation + propertyInfo.Name + " = " + propertySerialization + - Environment.NewLine); - } - - return objectSerialization.ToString(); - } - - private bool TrySerializeFinalType(object obj, out string serializedType) - { - var type = obj.GetType(); - if (settings.GetTypesSerializations().ContainsKey(type)) - { - serializedType = settings.GetTypesSerializations()[type].Invoke(obj); - - return true; - } - - if (settings.GetFinalTypes().Contains(type)) - { - serializedType = obj.ToString(); - if (settings.GetTypesWithCulture().ContainsKey(obj.GetType()) && obj is IFormattable) - serializedType = ((IFormattable)obj).ToString(null, settings.GetTypesWithCulture()[type]); - - return true; - } - - serializedType = ""; - - return false; - } - - private bool TrySerializeProperty(PropertyInfo propertyInfo, object obj, int nestingLevel, - out string serializedProperty) - { - serializedProperty = ""; - if (settings.GetExcludingProperties().Contains(propertyInfo) - || settings.GetExcludingTypes().Contains(propertyInfo.PropertyType)) - return false; - - var propertyMaxLength = settings.GetPropertiesToTrim().ContainsKey(propertyInfo) - ? settings.GetPropertiesToTrim()[propertyInfo] - : -1; - - serializedProperty = settings.GetPropertiesSerializations().ContainsKey(propertyInfo) - ? settings.GetPropertiesSerializations()[propertyInfo].Invoke(propertyInfo.GetValue(obj)) - : SerializeObject(propertyInfo.GetValue(obj), nestingLevel + 1).TrimEnd(); - - serializedProperty = propertyMaxLength >= 0 - ? serializedProperty[..settings.GetPropertiesToTrim()[propertyInfo]] - : serializedProperty; - - return true; - } - - private bool TrySerializeCollection(object obj, int nestingLevel, out string serializedCollection) - { - serializedCollection = ""; - var type = obj.GetType(); - if (!type.IsGenericType && !type.IsArray) - return false; - - if (type.IsArray || type.GetGenericTypeDefinition() == typeof(List<>)) - { - serializedCollection = SerializeEnumerable(obj, nestingLevel); - - return true; - } - - if (type.GetGenericTypeDefinition() == typeof(Dictionary<,>)) - { - serializedCollection = SerializeDictionary(obj, nestingLevel); - - return true; - } - - return false; - } - - private string SerializeEnumerable(object obj, int nestingLevel) - { - var enumerable = (IEnumerable)obj; - var serializedEnumerable = new StringBuilder(); - var identation = "\r\n" + new string('\t', nestingLevel + 1); - - foreach (var item in enumerable) - serializedEnumerable.Append(identation + SerializeObject(item, nestingLevel)); - - return serializedEnumerable.ToString(); - } - - private string SerializeDictionary(object obj, int nestingLevel) - { - var dict = (IDictionary)obj; - var serializedDict = new StringBuilder(); - var identation = "\r\n" + new string('\t', nestingLevel + 1); - - foreach (var pair in dict) - { - var key = ((DictionaryEntry)pair).Key; - var value = ((DictionaryEntry)pair).Value; - serializedDict.Append(identation + SerializeObject(key, nestingLevel) + " : " + - SerializeObject(value, nestingLevel)); - } - - return serializedDict.ToString(); - } - } -} \ No newline at end of file diff --git a/ObjectPrinting/Tests/File.cs b/ObjectPrinting/Tests/File.cs index f9f87216..5caf44d0 100644 --- a/ObjectPrinting/Tests/File.cs +++ b/ObjectPrinting/Tests/File.cs @@ -4,6 +4,7 @@ namespace ObjectPrinting.Tests { public class File { + public string field; public string Name { get; set; } public Dictionary Attributes { get; set; } diff --git a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs index 7915c0dd..439c9035 100644 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using System.Globalization; -using FluentAssertions; +using System.Globalization; using NUnit.Framework; namespace ObjectPrinting.Tests @@ -8,210 +6,21 @@ namespace ObjectPrinting.Tests [TestFixture] public class ObjectPrinterAcceptanceTests { - [SetUp] - public void SetUp() - { - _person = new Person { Name = "Alex", Age = 19, Height = 1.2 }; - } - - private Person _person; - - [Test] - public void PrintToString_ShouldReturnStringWithEveryObjectProperty() - { - var printer = ObjectPrinter.For(); - - var personWithEveryProperty = printer.PrintToString(_person); - - personWithEveryProperty - .Should() - .Be("Person\r\n\tId = Guid\r\n\tName = Alex\r\n\tHeight = 1,2\r\n\tAge = 19\r\n"); - } - - public void PrintToStringExcludingIntType_ShouldReturnStringWithNoIntProperty() - { - var printer = ObjectPrinter.For().Excluding(); - - var personWithNoIntProperties = printer.PrintToString(_person); - - personWithNoIntProperties.Should().Be("Person\r\n\tId = Guid\r\n\tName = Alex\r\n\tHeight = 1,2\r\n"); - } - - public void PrintToStringExcludingPropertyName_ShouldReturnStringWithNoNameProperty() - { - var printer = ObjectPrinter.For().Excluding(person => person.Name); - - var personWithNoNameProperty = printer.PrintToString(_person); - - personWithNoNameProperty.Should().Be("Person\r\n\tId = Guid\r\n\tHeight = 1,2\r\n\tAge = 19\r\n"); - } - - [Test] - public void PrintToStringUsingDoubleCultureInfo_ShouldReturnStringWithDoubleTypePropertyOfSetCulture() - { - var culture = new CultureInfo("en-US"); - var printer = ObjectPrinter.For().Printing().Using(culture); - - var personWithUSCultureForDouble = printer.PrintToString(_person); - - personWithUSCultureForDouble - .Should() - .Be("Person\r\n\tId = Guid\r\n\tName = Alex\r\n\tHeight = 1.2\r\n\tAge = 19\r\n"); - } - - [Test] - public void PrintToStringList_ShouldReturnStringWithEveryListObject() - { - var persons = new List { new Person { Age = 1, Height = 1.2 }, new Person { Age = 5 } }; - var printer = ObjectPrinter.For(); - - var listOfPersongWithEveryItem = printer.PrintToString(persons); - - listOfPersongWithEveryItem - .Should() - .Be("Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 1,2\r\n\tAge = 1\r\n" + - "Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 5\r\n"); - } - - [Test] - public void PrintToStringArray_ShouldReturnStringWithEveryArrayObject() - { - var persons = new[] { new Person { Age = 1, Height = 1.2 }, new Person { Age = 5 } }; - var printer = ObjectPrinter.For(); - - var arrayOfPersonsWithEveryItem = printer.PrintToString(persons); - - arrayOfPersonsWithEveryItem - .Should() - .Be("Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 1,2\r\n\tAge = 1\r\n" + - "Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 5\r\n"); - } - - [Test] - public void PrintToStringUsingCustomIntSerialization_ShouldReturnStringWithCustomSerializationForInt() - { - var printer = ObjectPrinter.For().Printing().Using(x => (x * 2).ToString()); - - var personWithEveryIntPropertyMultByTwo = printer.PrintToString(_person); - - personWithEveryIntPropertyMultByTwo - .Should() - .Be("Person\r\n\tId = Guid\r\n\tName = Alex\r\n\tHeight = 1,2\r\n\tAge = 38\r\n"); - } - [Test] - public void - PrintToStringUsingCustomPropertySerialization_ShouldReturnStringWithCustomSerializationForNameProperty() + public void Acceptance() { - var printer = ObjectPrinter - .For() - .Printing(person => person.Name) - .Using(name => $"My name is {name}"); - - var personWithCustomNamePropertySerializer = printer.PrintToString(_person); + var person = new Person { Name = "Alex", Age = 19, Height = 1.2 }; - personWithCustomNamePropertySerializer - .Should() - .Be("Person\r\n\tId = Guid\r\n\tName = My name is Alex\r\n\tHeight = 1,2\r\n\tAge = 19\r\n"); - } - - [Test] - public void PrintToStringTrimmingPropertySerialization_ShouldReturnStringWithTrimmedNameProperty() - { var printer = ObjectPrinter.For() + .Excluding() + .Printing() + .WithCulture(CultureInfo.CurrentCulture) + .Using(x => (x * 2).ToString()) .Printing(person => person.Name) - .TrimmedToLength(2); - - var personWithTrimmedNameProperty = printer.PrintToString(_person); - - personWithTrimmedNameProperty - .Should() - .Be("Person\r\n\tId = Guid\r\n\tName = Al\r\n\tHeight = 1,2\r\n\tAge = 19\r\n"); - } - - [Test] - public void PrintToStringObjectWithRefOnItself_ShouldReturnStringWithNoRecursedProperties() - { - var student = new Student(); - var anotherStudent = new Student { Teacher = student }; - student.Teacher = anotherStudent; - var printer = ObjectPrinter.For(); - - var studentWithTeacherRefOnItself = printer.PrintToString(student); - - studentWithTeacherRefOnItself - .Should() - .Be("Student\r\n\tTeacher = Student\r\n\t\t" - + "Teacher = Student\r\n\t\tId = Guid\r\n\t\tName = null\r\n\t\tHeight = 0\r\n\t\tAge = 0" - + "\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 0\r\n"); - } - - [Test] - public void PrintToStringObjectWithDictionary_ShouldReturnStringObjectWithSerializedDictionary() - { - var printer = ObjectPrinter.For(); - var file = new File { Name = "file", Attributes = new Dictionary { { "a", "b" } } }; - - var fileWithDictionaryProperty = printer.PrintToString(file); - - fileWithDictionaryProperty - .Should() - .Be( - "File\r\n\tName = file\r\n\tAttributes = \r\n\t\ta : b\r\n\tSimilarNames = null\r\n\tCopies = null\r\n"); - } - - [Test] - public void PrintToStringObjectWithList_ShouldReturnStringObjectWithSerializedList() - { - var printer = ObjectPrinter.For(); - var file = new File - { - Name = "file", - SimilarNames = new List { "oleg.jpg", "oleg.png" } - }; - - var fileWithListProperty = printer.PrintToString(file); - - fileWithListProperty - .Should() - .Be("File\r\n\tName = file\r\n\tAttributes = null\r\n\t" - + "SimilarNames = \r\n\t\toleg.jpg\r\n\t\toleg.png\r\n\tCopies = null\r\n"); - } - - [Test] - public void PrintToStringObjectWithArray_ShouldReturnStringObjectWithSerializedList() - { - var printer = ObjectPrinter.For(); - var file = new File - { - Name = "file", - Copies = new[] { "oleg.jpg", "oleg.png" } - }; - - var fileWithListProperty = printer.PrintToString(file); - - fileWithListProperty - .Should() - .Be("File\r\n\tName = file\r\n\tAttributes = null\r\n\tSimilarNames = null\r\n\t" - + "Copies = \r\n\t\toleg.jpg\r\n\t\toleg.png\r\n"); - } - - [Test] - public void PrintToStringDictionaryOfObjects_ShouldReturnStringWithSerializedDictionary() - { - var printer = ObjectPrinter.For(); - var dict = new Dictionary - { - { _person, "22" }, - { new Person(), "12" } - }; - - var fileWithListProperty = printer.PrintToString(dict); - - fileWithListProperty - .Should() - .Be("Person\r\n\tId = Guid\r\n\tName = Alex\r\n\tHeight = 1,2\r\n\tAge = 19\r\n : 22\r\n" - + "Person\r\n\tId = Guid\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 0\r\n : 12\r\n"); + .Using(name => $"{name}ing") + .TrimToLength(2) + .Excluding(person => person.Age) + .PrintRecursion(() => "Recursion"); } } } \ No newline at end of file diff --git a/ObjectPrinting/Tests/ObjectPrinterTests.cs b/ObjectPrinting/Tests/ObjectPrinterTests.cs new file mode 100644 index 00000000..e4e376e4 --- /dev/null +++ b/ObjectPrinting/Tests/ObjectPrinterTests.cs @@ -0,0 +1,344 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using FluentAssertions; +using NUnit.Framework; + +namespace ObjectPrinting.Tests +{ + [TestFixture] + public class ObjectPrinterTests + { + [SetUp] + public void SetUp() + { + _person = new Person { Name = "Alex", Age = 19, Height = 1.2 }; + } + + private Person _person; + + [Test] + public void PrintToString_ShouldReturnStringWithEveryObjectProperty() + { + var printer = ObjectPrinter.For(); + + var personWithEveryProperty = printer.PrintToString(_person); + + personWithEveryProperty + .Should() + .Be( + "Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\tName = Alex\r\n\tHeight = 1,2\r\n\tAge = 19\r\n"); + } + + [Test] + public void PrintToString_ShouldExcludeProperty_WhenItsTypeExcluded() + { + var printer = ObjectPrinter.For().Excluding(); + + var personWithNoIntProperties = printer.PrintToString(_person); + + personWithNoIntProperties.Should().Be("Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\t" + + "Name = Alex\r\n\tHeight = 1,2\r\n"); + } + + [Test] + public void PrintToString_ShouldExcludeProperty_WhenItsNameExcluded() + { + var printer = ObjectPrinter.For().Excluding(person => person.Name); + + var personWithNoNameProperty = printer.PrintToString(_person); + + personWithNoNameProperty.Should().Be("Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\t" + + "Height = 1,2\r\n\tAge = 19\r\n"); + } + + [Test] + public void PrintToString_ShouldUseTypeCulture_WhenItsSpecified() + { + var culture = new CultureInfo("en-US"); + var printer = ObjectPrinter.For().Printing().WithCulture(culture); + + var personWithUSCultureForDouble = printer.PrintToString(_person); + + personWithUSCultureForDouble + .Should() + .Be("Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\tName = Alex\r\n\t" + + "Height = 1.2\r\n\tAge = 19\r\n"); + } + + [Test] + public void PrintToString_ShouldReturnStringWithEveryListObject() + { + var persons = new List { new() { Age = 1, Height = 1.2 }, new() { Age = 5 } }; + var printer = ObjectPrinter.For>(); + + var listOfPersongWithEveryItem = printer.PrintToString(persons); + + listOfPersongWithEveryItem + .Should() + .Be( + "Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\tName = null\r\n\tHeight = 1,2\r\n\tAge = 1\r\n" + + "Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 5\r\n"); + } + + [Test] + public void PrintToString_ShouldReturnStringWithEveryArrayObject() + { + var persons = new[] { new Person { Age = 1, Height = 1.2 }, new Person { Age = 5 } }; + var printer = ObjectPrinter.For(); + + var arrayOfPersonsWithEveryItem = printer.PrintToString(persons); + + arrayOfPersonsWithEveryItem + .Should() + .Be( + "Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\tName = null\r\n\tHeight = 1,2\r\n\tAge = 1\r\n" + + "Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 5\r\n"); + } + + [Test] + public void PrintToString_ShouldReturnStringWithCustomSerializationForType_WhenItsSpecified() + { + var printer = ObjectPrinter.For().Printing().Using(x => (x * 2).ToString()); + + var personWithEveryIntPropertyMultByTwo = printer.PrintToString(_person); + + personWithEveryIntPropertyMultByTwo + .Should() + .Be( + "Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\tName = Alex\r\n\tHeight = 1,2\r\n\tAge = 38\r\n"); + } + + [Test] + public void + PrintToString_ShouldReturnStringWithCustomSerializationProperty_WhenItsSpecified() + { + var printer = ObjectPrinter + .For() + .Printing(person => person.Name) + .Using(name => $"My name is {name}"); + + var personWithCustomNamePropertySerializer = printer.PrintToString(_person); + + personWithCustomNamePropertySerializer + .Should() + .Be("Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\tName = My name is Alex\r\n\t" + + "Height = 1,2\r\n\tAge = 19\r\n"); + } + + [Test] + public void PrintToString_ShouldReturnStringWithCustomLength_WhenItsSpecified() + { + var printer = ObjectPrinter.For() + .Printing(person => person.Name) + .TrimToLength(2); + + var personWithTrimmedNameProperty = printer.PrintToString(_person); + + personWithTrimmedNameProperty + .Should() + .Be( + "Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\tName = Al\r\n\tHeight = 1,2\r\n\tAge = 19\r\n"); + } + + [Test] + public void PrintToString_ShouldReturnStringWithNoRecursedProperties() + { + var student = new Student { Name = "Alex", Age = 10 }; + var anotherStudent = new Student { Teacher = student, Name = "Vovchik", Age = 15 }; + student.Teacher = anotherStudent; + var printer = ObjectPrinter.For(); + + var studentWithTeacherRefOnItself = printer.PrintToString(student); + + studentWithTeacherRefOnItself + .Should() + .Be("Student\r\n\tTeacher = Student\r\n\t\tTeacher = Recursive property\r\n\t\t" + + "Friend = null\r\n\t\tId = 00000000-0000-0000-0000-000000000000\r\n\t\tName = Vovchik\r\n\t\t" + + "Height = 0\r\n\t\tAge = 15\r\n\tFriend = null\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\t" + + "Name = Alex\r\n\tHeight = 0\r\n\tAge = 10\r\n"); + } + + [Test] + public void PrintToString_ShouldReturnStringWithCustomRecursionSerialization_WhenItsSpecified() + { + var student = new Student { Name = "Alex", Age = 10 }; + var anotherStudent = new Student { Teacher = student, Name = "Vovchik", Age = 15 }; + student.Teacher = anotherStudent; + var printer = ObjectPrinter.For().PrintRecursion(() => "Recursion"); + + var studentWithTeacherRefOnItself = printer.PrintToString(student); + + studentWithTeacherRefOnItself + .Should() + .Be("Student\r\n\tTeacher = Student\r\n\t\tTeacher = Recursion\r\n\t\t" + + "Friend = null\r\n\t\tId = 00000000-0000-0000-0000-000000000000\r\n\t\tName = Vovchik\r\n\t\t" + + "Height = 0\r\n\t\tAge = 15\r\n\tFriend = null\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\t" + + "Name = Alex\r\n\tHeight = 0\r\n\tAge = 10\r\n"); + } + + [Test] + public void PrintToString_ShouldThrowException_WhenPropertyRecursed() + { + var student = new Student { Name = "Alex", Age = 10 }; + var anotherStudent = new Student { Teacher = student, Name = "Vovchik", Age = 15 }; + student.Teacher = anotherStudent; + var printer = ObjectPrinter.For().PrintRecursion(new Exception()); + + Assert.Throws(() => printer.PrintToString(student)); + } + + [Test] + public void PrintToString_ShouldPrintAllObjects_WhenTheyHaveConnectedRefs() + { + var firstStudent = new Student { Name = "Alex", Age = 10 }; + var secondStudent = new Student { Name = "Miha", Age = 15 }; + var thirdstudent = new Student { Name = "Petr", Age = 12 }; + firstStudent.Teacher = thirdstudent; + firstStudent.Friend = secondStudent; + secondStudent.Teacher = thirdstudent; + var printer = ObjectPrinter.For(); + + var notRecursedStudents = printer.PrintToString(firstStudent); + + notRecursedStudents.Should() + .Be("Student\r\n\tTeacher = Student\r\n\t\tTeacher = null\r\n\t\t" + + "Friend = null\r\n\t\tId = 00000000-0000-0000-0000-000000000000\r\n\t\tName = Petr\r\n\t\t" + + "Height = 0\r\n\t\tAge = 12\r\n\tFriend = Student\r\n\t\tTeacher = Student\r\n\t\t\t" + + "Teacher = null\r\n\t\t\tFriend = null\r\n\t\t\tId = 00000000-0000-0000-0000-000000000000\r\n\t\t\t" + + "Name = Petr\r\n\t\t\tHeight = 0\r\n\t\t\tAge = 12\r\n\t\tFriend = null\r\n\t\t" + + "Id = 00000000-0000-0000-0000-000000000000\r\n\t\tName = Miha\r\n\t\tHeight = 0\r\n\t\tAge = 15\r\n\t" + + "Id = 00000000-0000-0000-0000-000000000000\r\n\tName = Alex\r\n\tHeight = 0\r\n\tAge = 10\r\n"); + } + + [Test] + public void PrintToString_ShouldReturnStringObjectWithSerializedDictionary() + { + var printer = ObjectPrinter.For(); + var file = new File { Name = "file", Attributes = new Dictionary { { "a", "b" } } }; + + var fileWithDictionaryProperty = printer.PrintToString(file); + + fileWithDictionaryProperty + .Should() + .Be("File\r\n\tName = file\r\n\tAttributes = \r\n\t\tKeyValuePair`2\r\n\t\tKey = a\r\n\t\t" + + "Value = b\r\n\tSimilarNames = null\r\n\tCopies = null\r\n\tfield = null\r\n"); + } + + [Test] + public void PrintToString_ShouldReturnStringObjectWithSerializedList() + { + var printer = ObjectPrinter.For(); + var file = new File + { + Name = "file", + SimilarNames = new List { "oleg.jpg", "oleg.png" } + }; + + var fileWithListProperty = printer.PrintToString(file); + + fileWithListProperty + .Should() + .Be("File\r\n\tName = file\r\n\tAttributes = null\r\n\tSimilarNames = \r\n\t\toleg.jpg\r\n\t\t" + + "oleg.png\r\n\tCopies = null\r\n\tfield = null\r\n"); + } + + [Test] + public void PrintToString_ShouldReturnStringObjectWithSerializedArray() + { + var printer = ObjectPrinter.For(); + var file = new File + { + Name = "file", + Copies = new[] { "oleg.jpg", "oleg.png" } + }; + + var fileWithListProperty = printer.PrintToString(file); + + fileWithListProperty + .Should() + .Be("File\r\n\tName = file\r\n\tAttributes = null\r\n\tSimilarNames = null\r\n\tCopies = \r\n\t\t" + + "oleg.jpg\r\n\t\toleg.png\r\n\tfield = null\r\n"); + } + + [Test] + public void PrintToString_ShouldReturnStringWithSerializedDictionary() + { + var printer = ObjectPrinter.For>(); + var dict = new Dictionary + { + { _person, "22" }, + { new Person(), "12" } + }; + + var fileWithListProperty = printer.PrintToString(dict); + + fileWithListProperty + .Should() + .Be("KeyValuePair`2\r\n\tKey = Person\r\n\t\tId = 00000000-0000-0000-0000-000000000000\r\n\t\t" + + "Name = Alex\r\n\t\tHeight = 1,2\r\n\t\tAge = 19\r\n\tValue = 22\r\nKeyValuePair`2\r\n\tKey = Person\r\n\t\t" + + "Id = 00000000-0000-0000-0000-000000000000\r\n\t\tName = null\r\n\t\tHeight = 0\r\n\t\tAge = 0\r\n\tValue = 12\r\n"); + } + + [Test] + public void PrintToString_ShouldPrintListWithNullValue_WhenEmptyListPassed() + { + var printer = ObjectPrinter.For(); + var file = new File + { + Name = "file" + }; + + var fileWithListProperty = printer.PrintToString(file); + + fileWithListProperty + .Should() + .Be("File\r\n\tName = file\r\n\tAttributes = null\r\n\tSimilarNames = null\r\n\t" + + "Copies = null\r\n\tfield = null\r\n"); + } + + [Test] + public void PrintToString_ShouldPrintArrayWithNullValue_WhenEmptyArrayPassed() + { + var printer = ObjectPrinter.For(); + var file = new File + { + Name = "file" + }; + + var fileWithListProperty = printer.PrintToString(file); + + fileWithListProperty + .Should() + .Be("File\r\n\tName = file\r\n\tAttributes = null\r\n\tSimilarNames = null\r\n\t" + + "Copies = null\r\n\tfield = null\r\n"); + } + + [Test] + public void PrintToString_ShouldPrintDictionaryWithNullValue_WhenEmptyDictionaryPassed() + { + var printer = ObjectPrinter.For(); + var file = new File + { + Name = "file" + }; + + var fileWithListProperty = printer.PrintToString(file); + + fileWithListProperty + .Should() + .Be("File\r\n\tName = file\r\n\tAttributes = null\r\n\tSimilarNames = null\r\n\t" + + "Copies = null\r\n\tfield = null\r\n"); + } + + [Test] + public void TrimToLength_ShouldThrowArgumentException_WhenPassedNegativeLength() + { + var printer = ObjectPrinter.For() + .Printing(person => person.Name); + + + Assert.Throws(() => printer.TrimToLength(-1)); + } + } +} \ No newline at end of file diff --git a/ObjectPrinting/Tests/Student.cs b/ObjectPrinting/Tests/Student.cs index cbac7a8b..6ab9d89e 100644 --- a/ObjectPrinting/Tests/Student.cs +++ b/ObjectPrinting/Tests/Student.cs @@ -3,5 +3,7 @@ public class Student : Person { public Person Teacher { get; set; } + + public Person Friend { get; set; } } } \ No newline at end of file diff --git a/ObjectPrinting/TypePrintingConfig.cs b/ObjectPrinting/TypePrintingConfig.cs new file mode 100644 index 00000000..9ba05941 --- /dev/null +++ b/ObjectPrinting/TypePrintingConfig.cs @@ -0,0 +1,26 @@ +using System; +using System.Globalization; + +namespace ObjectPrinting +{ + public class TypePrintingConfig : PrintingConfig + { + public TypePrintingConfig(PrintingConfig config) : base(config) + { + } + + public TypePrintingConfig WithCulture(CultureInfo cultureInfo) where T : IFormattable + { + typesCulture.Add(typeof(T), cultureInfo); + + return this; + } + + public TypePrintingConfig Using(Func printType) + { + typesSerialization.TryAdd(typeof(TPropType), type => printType((TPropType)type)); + + return this; + } + } +} \ No newline at end of file From a68eb7cd664c2eb35c7f1c04709133fae0a9fdef Mon Sep 17 00:00:00 2001 From: daHil Date: Wed, 27 Dec 2023 19:16:42 +0700 Subject: [PATCH 6/6] refactored after feedback --- ObjectPrinting/MemberInfoExtension.cs | 28 +++ ObjectPrinting/PrintingConfig.cs | 72 ++++---- ObjectPrinting/PropertyPrintingConfig.cs | 7 +- ObjectPrinting/Tests/LinkedNode.cs | 9 + .../Tests/ObjectPrinterAcceptanceTests.cs | 12 +- ObjectPrinting/Tests/ObjectPrinterTests.cs | 162 +++++++++++------- ObjectPrinting/TypePrintingConfig.cs | 4 +- 7 files changed, 195 insertions(+), 99 deletions(-) create mode 100644 ObjectPrinting/MemberInfoExtension.cs create mode 100644 ObjectPrinting/Tests/LinkedNode.cs diff --git a/ObjectPrinting/MemberInfoExtension.cs b/ObjectPrinting/MemberInfoExtension.cs new file mode 100644 index 00000000..5d1f88b6 --- /dev/null +++ b/ObjectPrinting/MemberInfoExtension.cs @@ -0,0 +1,28 @@ +using System; +using System.Reflection; + +namespace ObjectPrinting +{ + public static class MemberInfoExtension + { + public static object GetMemberValue(this MemberInfo memberInfo, object obj) + { + return memberInfo switch + { + PropertyInfo propertyInfo => propertyInfo.GetValue(obj), + FieldInfo fieldInfo => fieldInfo.GetValue(obj), + _ => throw new InvalidOperationException() + }; + } + + public static Type GetMemberType(this MemberInfo memberInfo) + { + return memberInfo switch + { + PropertyInfo propertyInfo => propertyInfo.PropertyType, + FieldInfo fieldInfo => fieldInfo.FieldType, + _ => throw new InvalidOperationException() + }; + } + } +} \ No newline at end of file diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 40af3a6c..ba561eba 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -52,12 +52,11 @@ public PrintingConfig Excluding() return this; } - public PrintingConfig Excluding(Expression> property) + public PrintingConfig Excluding(Expression> member) { - var memberBody = (MemberExpression)property.Body; - var propertyInfo = memberBody.Member; + var memberInfo = GetMember(member); - excludedProperties.Add(propertyInfo); + excludedProperties.Add(memberInfo); return this; } @@ -68,28 +67,34 @@ public TypePrintingConfig Printing() } public PropertyPrintingConfig Printing( - Expression> printProperty) + Expression> printMember) { - var memberBody = (MemberExpression)printProperty.Body; - var propertyInfo = memberBody.Member; + var memberInfo = GetMember(printMember); - return new PropertyPrintingConfig(this, propertyInfo); + return new PropertyPrintingConfig(this, memberInfo); } - public PrintingConfig PrintRecursion(Exception exception) + public PrintingConfig WithCyclicLinkException() { - recursivePropertiesSerialization = () => throw exception; + recursivePropertiesSerialization = () => throw new ArgumentException("recursive property"); return this; } - public PrintingConfig PrintRecursion(Func printProperty) + public PrintingConfig WithCyclicLinkMessage(Func printProperty) { recursivePropertiesSerialization = printProperty; return this; } + public PrintingConfig WithCyclicLinkIgnored() + { + recursivePropertiesSerialization = () => string.Empty; + + return this; + } + private string SerializeObject(object obj, IImmutableList previousObjects) { if (obj == null) @@ -98,33 +103,27 @@ private string SerializeObject(object obj, IImmutableList previousObject var type = obj.GetType(); if (previousObjects.Any(prev => prev == obj)) { - if (recursivePropertiesSerialization != null) - return recursivePropertiesSerialization(); - return "Recursive property"; + return recursivePropertiesSerialization != null + ? (string)recursivePropertiesSerialization() : "Recursive property"; } - if (obj is IEnumerable && obj is not string) return SerializeEnumerable(obj, previousObjects); if (_finalTypes.Contains(type)) return SerializeFinalType(obj); - var identation = new string('\t', previousObjects.Count + 1); + var indentation = new string('\t', previousObjects.Count + 1); + var objectSerialization = new StringBuilder().AppendLine(type.Name); previousObjects = previousObjects.Add(obj); - var objectSerialization = new StringBuilder(); - objectSerialization.AppendLine(type.Name); var members = Array.Empty().Concat(type.GetProperties()).Concat(type.GetFields()); foreach (var memberInfo in members) { - var memberType = memberInfo.MemberType == MemberTypes.Property - ? (memberInfo as PropertyInfo).PropertyType - : (memberInfo as FieldInfo).FieldType; if (excludedProperties.Contains(memberInfo) - || excludedTypes.Contains(memberType)) + || excludedTypes.Contains(memberInfo.GetMemberType())) continue; - objectSerialization.Append(identation); + objectSerialization.Append(indentation); objectSerialization.Append(memberInfo.Name); objectSerialization.Append(" = "); objectSerialization.Append(SerializeMember(memberInfo, obj, previousObjects)); @@ -149,36 +148,43 @@ private string SerializeFinalType(object obj) private string SerializeMember(MemberInfo memberInfo, object obj, IImmutableList previousObjects) { - var value = memberInfo.MemberType == MemberTypes.Property - ? (memberInfo as PropertyInfo).GetValue(obj) - : (memberInfo as FieldInfo).GetValue(obj); - var serializedProperty = propertiesSerialization.TryGetValue(memberInfo, out var serialization) + var value = memberInfo.GetMemberValue(obj); + var result = propertiesSerialization.TryGetValue(memberInfo, out var serialization) ? serialization.Invoke(value) : SerializeObject(value, previousObjects).TrimEnd(); var propertyMaxLength = propertiesMaxLength.TryGetValue(memberInfo, out var length) ? length - : serializedProperty.Length; + : result.Length; - serializedProperty = serializedProperty[..propertyMaxLength]; + result = result[..propertyMaxLength]; - return serializedProperty; + return result; } private string SerializeEnumerable(object obj, IImmutableList previousObjects) { var enumerable = (IEnumerable)obj; var serializedEnumerable = new StringBuilder(); - var nestingLevel = previousObjects.Count == 0 ? 0 : previousObjects.Count + 1; - var identation = nestingLevel == 0 ? "" : Environment.NewLine + new string('\t', nestingLevel); + var indentation = previousObjects.Count == 0 + ? string.Empty + : Environment.NewLine + new string('\t', previousObjects.Count + 1); foreach (var item in enumerable) { - serializedEnumerable.Append(identation); + serializedEnumerable.Append(indentation); serializedEnumerable.Append(SerializeObject(item, previousObjects)); } return serializedEnumerable.ToString(); } + + private static MemberInfo GetMember(Expression> expression) + { + var memberBody = (MemberExpression)expression.Body; + var memberInfo = memberBody.Member; + + return memberInfo; + } } } \ No newline at end of file diff --git a/ObjectPrinting/PropertyPrintingConfig.cs b/ObjectPrinting/PropertyPrintingConfig.cs index e5108b47..a137241e 100644 --- a/ObjectPrinting/PropertyPrintingConfig.cs +++ b/ObjectPrinting/PropertyPrintingConfig.cs @@ -12,17 +12,16 @@ public PropertyPrintingConfig(PrintingConfig config, MemberInfo property this.propertyInfo = propertyInfo; } - public PropertyPrintingConfig Using(Func printProperty) + public PropertyPrintingConfig Using(Func printProperty) { - propertiesSerialization.TryAdd(propertyInfo, type => printProperty((TPropType)type)); + propertiesSerialization.TryAdd(propertyInfo, printProperty); return this; } public PropertyPrintingConfig TrimToLength(int length) { - if (length < 0) - throw new ArgumentException("length can not be negative"); + ArgumentOutOfRangeException.ThrowIfNegative(length); propertiesMaxLength.Add(propertyInfo, length); diff --git a/ObjectPrinting/Tests/LinkedNode.cs b/ObjectPrinting/Tests/LinkedNode.cs new file mode 100644 index 00000000..cc0b3588 --- /dev/null +++ b/ObjectPrinting/Tests/LinkedNode.cs @@ -0,0 +1,9 @@ +namespace ObjectPrinting.Tests +{ + public class LinkedNode + { + public T Value { get; set; } + + public LinkedNode Next { get; set; } + } +} \ No newline at end of file diff --git a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs index 439c9035..28f2a8ea 100644 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs @@ -1,4 +1,5 @@ using System.Globalization; +using FluentAssertions; using NUnit.Framework; namespace ObjectPrinting.Tests @@ -7,7 +8,7 @@ namespace ObjectPrinting.Tests public class ObjectPrinterAcceptanceTests { [Test] - public void Acceptance() + public void AcceptanceTest() { var person = new Person { Name = "Alex", Age = 19, Height = 1.2 }; @@ -20,7 +21,14 @@ public void Acceptance() .Using(name => $"{name}ing") .TrimToLength(2) .Excluding(person => person.Age) - .PrintRecursion(() => "Recursion"); + .WithCyclicLinkMessage(() => "Recursion") + .WithCyclicLinkIgnored() + .WithCyclicLinkException(); + + var printedPerson = printer.PrintToString(person); + + printedPerson.Should().Be("Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\t" + + "Name = Al\r\n\tHeight = 2,4\r\n"); } } } \ No newline at end of file diff --git a/ObjectPrinting/Tests/ObjectPrinterTests.cs b/ObjectPrinting/Tests/ObjectPrinterTests.cs index e4e376e4..f681d747 100644 --- a/ObjectPrinting/Tests/ObjectPrinterTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterTests.cs @@ -12,22 +12,22 @@ public class ObjectPrinterTests [SetUp] public void SetUp() { - _person = new Person { Name = "Alex", Age = 19, Height = 1.2 }; + person = new Person { Name = "Alex", Age = 19, Height = 1.2 }; } - private Person _person; + private Person person; [Test] public void PrintToString_ShouldReturnStringWithEveryObjectProperty() { var printer = ObjectPrinter.For(); - var personWithEveryProperty = printer.PrintToString(_person); + var personWithEveryProperty = printer.PrintToString(person); personWithEveryProperty .Should() - .Be( - "Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\tName = Alex\r\n\tHeight = 1,2\r\n\tAge = 19\r\n"); + .Be("Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\t" + + "Name = Alex\r\n\tHeight = 1,2\r\n\tAge = 19\r\n"); } [Test] @@ -35,10 +35,10 @@ public void PrintToString_ShouldExcludeProperty_WhenItsTypeExcluded() { var printer = ObjectPrinter.For().Excluding(); - var personWithNoIntProperties = printer.PrintToString(_person); + var personWithoutIntProperties = printer.PrintToString(person); - personWithNoIntProperties.Should().Be("Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\t" + - "Name = Alex\r\n\tHeight = 1,2\r\n"); + personWithoutIntProperties.Should().Be("Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\t" + + "Name = Alex\r\n\tHeight = 1,2\r\n"); } [Test] @@ -46,10 +46,10 @@ public void PrintToString_ShouldExcludeProperty_WhenItsNameExcluded() { var printer = ObjectPrinter.For().Excluding(person => person.Name); - var personWithNoNameProperty = printer.PrintToString(_person); + var personWithoutNameProperty = printer.PrintToString(person); - personWithNoNameProperty.Should().Be("Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\t" + - "Height = 1,2\r\n\tAge = 19\r\n"); + personWithoutNameProperty.Should().Be("Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\t" + + "Height = 1,2\r\n\tAge = 19\r\n"); } [Test] @@ -58,7 +58,7 @@ public void PrintToString_ShouldUseTypeCulture_WhenItsSpecified() var culture = new CultureInfo("en-US"); var printer = ObjectPrinter.For().Printing().WithCulture(culture); - var personWithUSCultureForDouble = printer.PrintToString(_person); + var personWithUSCultureForDouble = printer.PrintToString(person); personWithUSCultureForDouble .Should() @@ -67,14 +67,14 @@ public void PrintToString_ShouldUseTypeCulture_WhenItsSpecified() } [Test] - public void PrintToString_ShouldReturnStringWithEveryListObject() + public void PrintToString_ShouldReturnStringWithEveryListObject_WhenListPassed() { var persons = new List { new() { Age = 1, Height = 1.2 }, new() { Age = 5 } }; var printer = ObjectPrinter.For>(); - var listOfPersongWithEveryItem = printer.PrintToString(persons); + var listOfPersonsWithEveryItem = printer.PrintToString(persons); - listOfPersongWithEveryItem + listOfPersonsWithEveryItem .Should() .Be( "Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\tName = null\r\n\tHeight = 1,2\r\n\tAge = 1\r\n" + @@ -82,7 +82,7 @@ public void PrintToString_ShouldReturnStringWithEveryListObject() } [Test] - public void PrintToString_ShouldReturnStringWithEveryArrayObject() + public void PrintToString_ShouldReturnStringWithEveryArrayObject_WhenArrayPassed() { var persons = new[] { new Person { Age = 1, Height = 1.2 }, new Person { Age = 5 } }; var printer = ObjectPrinter.For(); @@ -96,17 +96,37 @@ public void PrintToString_ShouldReturnStringWithEveryArrayObject() "Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\tName = null\r\n\tHeight = 0\r\n\tAge = 5\r\n"); } + [Test] + public void PrintToString_ShouldReturnStringWithEveryDictionaryObject_WhenDictionaryPassed() + { + var printer = ObjectPrinter.For>(); + var dict = new Dictionary + { + { person, "22" }, + { new Person(), "12" } + }; + + var fileWithListProperty = printer.PrintToString(dict); + + fileWithListProperty + .Should() + .Be("KeyValuePair`2\r\n\tKey = Person\r\n\t\tId = 00000000-0000-0000-0000-000000000000\r\n\t\t" + + "Name = Alex\r\n\t\tHeight = 1,2\r\n\t\tAge = 19\r\n\tValue = 22\r\nKeyValuePair`2\r\n\t" + + "Key = Person\r\n\t\tId = 00000000-0000-0000-0000-000000000000\r\n\t\t" + + "Name = null\r\n\t\tHeight = 0\r\n\t\tAge = 0\r\n\tValue = 12\r\n"); + } + [Test] public void PrintToString_ShouldReturnStringWithCustomSerializationForType_WhenItsSpecified() { var printer = ObjectPrinter.For().Printing().Using(x => (x * 2).ToString()); - var personWithEveryIntPropertyMultByTwo = printer.PrintToString(_person); + var personWithEveryIntPropertyMultByTwo = printer.PrintToString(person); personWithEveryIntPropertyMultByTwo .Should() - .Be( - "Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\tName = Alex\r\n\tHeight = 1,2\r\n\tAge = 38\r\n"); + .Be("Person\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\t" + + "Name = Alex\r\n\tHeight = 1,2\r\n\tAge = 38\r\n"); } [Test] @@ -118,7 +138,7 @@ public void .Printing(person => person.Name) .Using(name => $"My name is {name}"); - var personWithCustomNamePropertySerializer = printer.PrintToString(_person); + var personWithCustomNamePropertySerializer = printer.PrintToString(person); personWithCustomNamePropertySerializer .Should() @@ -133,7 +153,7 @@ public void PrintToString_ShouldReturnStringWithCustomLength_WhenItsSpecified() .Printing(person => person.Name) .TrimToLength(2); - var personWithTrimmedNameProperty = printer.PrintToString(_person); + var personWithTrimmedNameProperty = printer.PrintToString(person); personWithTrimmedNameProperty .Should() @@ -142,7 +162,7 @@ public void PrintToString_ShouldReturnStringWithCustomLength_WhenItsSpecified() } [Test] - public void PrintToString_ShouldReturnStringWithNoRecursedProperties() + public void PrintToString_ShouldReturnStringWithoutRecursion_WhenObjectRefersOnItself() { var student = new Student { Name = "Alex", Age = 10 }; var anotherStudent = new Student { Teacher = student, Name = "Vovchik", Age = 15 }; @@ -159,13 +179,30 @@ public void PrintToString_ShouldReturnStringWithNoRecursedProperties() "Name = Alex\r\n\tHeight = 0\r\n\tAge = 10\r\n"); } + [Test] + public void PrintToString_ShouldReturnStringWithoutRecursion_WhenLinkedListRecured() + { + var firstLinkedNode = new LinkedNode(); + var secondLinkedNode = new LinkedNode(); + var thirdLinkedNode = new LinkedNode(); + firstLinkedNode.Next = secondLinkedNode; + secondLinkedNode.Next = thirdLinkedNode; + thirdLinkedNode.Next = firstLinkedNode; + var printer = ObjectPrinter.For>(); + + var printedList = printer.PrintToString(firstLinkedNode); + + printedList.Should().Be("LinkedNode`1\r\n\tValue = 0\r\n\tNext = LinkedNode`1\r\n\t\tValue = 0\r\n\t\t" + + "Next = LinkedNode`1\r\n\t\t\tValue = 0\r\n\t\t\tNext = Recursive property\r\n"); + } + [Test] public void PrintToString_ShouldReturnStringWithCustomRecursionSerialization_WhenItsSpecified() { var student = new Student { Name = "Alex", Age = 10 }; var anotherStudent = new Student { Teacher = student, Name = "Vovchik", Age = 15 }; student.Teacher = anotherStudent; - var printer = ObjectPrinter.For().PrintRecursion(() => "Recursion"); + var printer = ObjectPrinter.For().WithCyclicLinkMessage(() => "Recursion"); var studentWithTeacherRefOnItself = printer.PrintToString(student); @@ -177,15 +214,33 @@ public void PrintToString_ShouldReturnStringWithCustomRecursionSerialization_Whe "Name = Alex\r\n\tHeight = 0\r\n\tAge = 10\r\n"); } + [Test] + public void PrintToString_ShouldReturnStringWithIgnoredRecuresdProperty_WhenItsSpecified() + { + var student = new Student { Name = "Alex", Age = 10 }; + var anotherStudent = new Student { Teacher = student, Name = "Vovchik", Age = 15 }; + student.Teacher = anotherStudent; + var printer = ObjectPrinter.For().WithCyclicLinkIgnored(); + + var studentWithTeacherRefOnItself = printer.PrintToString(student); + + studentWithTeacherRefOnItself + .Should() + .Be("Student\r\n\tTeacher = Student\r\n\t\tTeacher = \r\n\t\t" + + "Friend = null\r\n\t\tId = 00000000-0000-0000-0000-000000000000\r\n\t\tName = Vovchik\r\n\t\t" + + "Height = 0\r\n\t\tAge = 15\r\n\tFriend = null\r\n\tId = 00000000-0000-0000-0000-000000000000\r\n\t" + + "Name = Alex\r\n\tHeight = 0\r\n\tAge = 10\r\n"); + } + [Test] public void PrintToString_ShouldThrowException_WhenPropertyRecursed() { var student = new Student { Name = "Alex", Age = 10 }; var anotherStudent = new Student { Teacher = student, Name = "Vovchik", Age = 15 }; student.Teacher = anotherStudent; - var printer = ObjectPrinter.For().PrintRecursion(new Exception()); + var printer = ObjectPrinter.For().WithCyclicLinkException(); - Assert.Throws(() => printer.PrintToString(student)); + Assert.Throws(() => printer.PrintToString(student)); } [Test] @@ -203,16 +258,16 @@ public void PrintToString_ShouldPrintAllObjects_WhenTheyHaveConnectedRefs() notRecursedStudents.Should() .Be("Student\r\n\tTeacher = Student\r\n\t\tTeacher = null\r\n\t\t" + - "Friend = null\r\n\t\tId = 00000000-0000-0000-0000-000000000000\r\n\t\tName = Petr\r\n\t\t" + - "Height = 0\r\n\t\tAge = 12\r\n\tFriend = Student\r\n\t\tTeacher = Student\r\n\t\t\t" + - "Teacher = null\r\n\t\t\tFriend = null\r\n\t\t\tId = 00000000-0000-0000-0000-000000000000\r\n\t\t\t" + - "Name = Petr\r\n\t\t\tHeight = 0\r\n\t\t\tAge = 12\r\n\t\tFriend = null\r\n\t\t" + - "Id = 00000000-0000-0000-0000-000000000000\r\n\t\tName = Miha\r\n\t\tHeight = 0\r\n\t\tAge = 15\r\n\t" + - "Id = 00000000-0000-0000-0000-000000000000\r\n\tName = Alex\r\n\tHeight = 0\r\n\tAge = 10\r\n"); + "Friend = null\r\n\t\tId = 00000000-0000-0000-0000-000000000000\r\n\t\tName = Petr\r\n\t\t" + + "Height = 0\r\n\t\tAge = 12\r\n\tFriend = Student\r\n\t\tTeacher = Student\r\n\t\t\t" + + "Teacher = null\r\n\t\t\tFriend = null\r\n\t\t\tId = 00000000-0000-0000-0000-000000000000\r\n\t\t\t" + + "Name = Petr\r\n\t\t\tHeight = 0\r\n\t\t\tAge = 12\r\n\t\tFriend = null\r\n\t\t" + + "Id = 00000000-0000-0000-0000-000000000000\r\n\t\tName = Miha\r\n\t\tHeight = 0\r\n\t\tAge = 15\r\n\t" + + "Id = 00000000-0000-0000-0000-000000000000\r\n\tName = Alex\r\n\tHeight = 0\r\n\tAge = 10\r\n"); } [Test] - public void PrintToString_ShouldReturnStringObjectWithSerializedDictionary() + public void PrintToString_ShouldReturnStringObjectWithSerializedDictionary_WhenObjectHasDictionary() { var printer = ObjectPrinter.For(); var file = new File { Name = "file", Attributes = new Dictionary { { "a", "b" } } }; @@ -226,7 +281,7 @@ public void PrintToString_ShouldReturnStringObjectWithSerializedDictionary() } [Test] - public void PrintToString_ShouldReturnStringObjectWithSerializedList() + public void PrintToString_ShouldReturnStringObjectWithSerializedList_WhenObjectHasList() { var printer = ObjectPrinter.For(); var file = new File @@ -244,7 +299,7 @@ public void PrintToString_ShouldReturnStringObjectWithSerializedList() } [Test] - public void PrintToString_ShouldReturnStringObjectWithSerializedArray() + public void PrintToString_ShouldReturnStringObjectWithSerializedArray_WhenObjectHasArray() { var printer = ObjectPrinter.For(); var file = new File @@ -262,26 +317,7 @@ public void PrintToString_ShouldReturnStringObjectWithSerializedArray() } [Test] - public void PrintToString_ShouldReturnStringWithSerializedDictionary() - { - var printer = ObjectPrinter.For>(); - var dict = new Dictionary - { - { _person, "22" }, - { new Person(), "12" } - }; - - var fileWithListProperty = printer.PrintToString(dict); - - fileWithListProperty - .Should() - .Be("KeyValuePair`2\r\n\tKey = Person\r\n\t\tId = 00000000-0000-0000-0000-000000000000\r\n\t\t" + - "Name = Alex\r\n\t\tHeight = 1,2\r\n\t\tAge = 19\r\n\tValue = 22\r\nKeyValuePair`2\r\n\tKey = Person\r\n\t\t" + - "Id = 00000000-0000-0000-0000-000000000000\r\n\t\tName = null\r\n\t\tHeight = 0\r\n\t\tAge = 0\r\n\tValue = 12\r\n"); - } - - [Test] - public void PrintToString_ShouldPrintListWithNullValue_WhenEmptyListPassed() + public void PrintToString_ShouldPrintListWithNullValue_WhenObjectHasEmptyList() { var printer = ObjectPrinter.For(); var file = new File @@ -298,7 +334,7 @@ public void PrintToString_ShouldPrintListWithNullValue_WhenEmptyListPassed() } [Test] - public void PrintToString_ShouldPrintArrayWithNullValue_WhenEmptyArrayPassed() + public void PrintToString_ShouldPrintArrayWithNullValue_WhenObjectHasEmptyArray() { var printer = ObjectPrinter.For(); var file = new File @@ -315,7 +351,7 @@ public void PrintToString_ShouldPrintArrayWithNullValue_WhenEmptyArrayPassed() } [Test] - public void PrintToString_ShouldPrintDictionaryWithNullValue_WhenEmptyDictionaryPassed() + public void PrintToString_ShouldPrintDictionaryWithNullValue_WhenObjectHasEmptyDictionary() { var printer = ObjectPrinter.For(); var file = new File @@ -332,13 +368,23 @@ public void PrintToString_ShouldPrintDictionaryWithNullValue_WhenEmptyDictionary } [Test] - public void TrimToLength_ShouldThrowArgumentException_WhenPassedNegativeLength() + public void TrimToLength_ShouldThrowArgumentOutOfRangeException_WhenPassedNegativeLength() { var printer = ObjectPrinter.For() .Printing(person => person.Name); - Assert.Throws(() => printer.TrimToLength(-1)); + Assert.Throws(() => printer.TrimToLength(-1)); + } + + [Test] + public void PrintToString_ShouldThrowArgumentOutOfRangeException_WhenTrimToLengthBiggerThanPropertyLength() + { + var printer = ObjectPrinter.For() + .Printing(person => person.Name).TrimToLength(20); + + + Assert.Throws(() => printer.PrintToString(person)); } } } \ No newline at end of file diff --git a/ObjectPrinting/TypePrintingConfig.cs b/ObjectPrinting/TypePrintingConfig.cs index 9ba05941..6396c9af 100644 --- a/ObjectPrinting/TypePrintingConfig.cs +++ b/ObjectPrinting/TypePrintingConfig.cs @@ -16,9 +16,9 @@ public TypePrintingConfig WithCulture(CultureInfo cultureI return this; } - public TypePrintingConfig Using(Func printType) + public TypePrintingConfig Using(Func printType) { - typesSerialization.TryAdd(typeof(TPropType), type => printType((TPropType)type)); + typesSerialization.TryAdd(typeof(TPropType), printType); return this; }