From 4a7015ef0b16cd42d5142b720db6c5c7ee385bce Mon Sep 17 00:00:00 2001 From: S4MPAI Date: Tue, 10 Dec 2024 01:33:02 +0500 Subject: [PATCH 01/12] delete folder Solved --- ObjectPrinting/Solved/ObjectExtensions.cs | 10 --- ObjectPrinting/Solved/ObjectPrinter.cs | 10 --- ObjectPrinting/Solved/PrintingConfig.cs | 62 ------------------- .../Solved/PropertyPrintingConfig.cs | 32 ---------- .../PropertyPrintingConfigExtensions.cs | 18 ------ .../Tests/ObjectPrinterAcceptanceTests.cs | 40 ------------ ObjectPrinting/Solved/Tests/Person.cs | 12 ---- 7 files changed, 184 deletions(-) delete mode 100644 ObjectPrinting/Solved/ObjectExtensions.cs delete mode 100644 ObjectPrinting/Solved/ObjectPrinter.cs delete mode 100644 ObjectPrinting/Solved/PrintingConfig.cs delete mode 100644 ObjectPrinting/Solved/PropertyPrintingConfig.cs delete mode 100644 ObjectPrinting/Solved/PropertyPrintingConfigExtensions.cs delete mode 100644 ObjectPrinting/Solved/Tests/ObjectPrinterAcceptanceTests.cs delete mode 100644 ObjectPrinting/Solved/Tests/Person.cs diff --git a/ObjectPrinting/Solved/ObjectExtensions.cs b/ObjectPrinting/Solved/ObjectExtensions.cs deleted file mode 100644 index b0c94553..00000000 --- a/ObjectPrinting/Solved/ObjectExtensions.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ObjectPrinting.Solved -{ - public static class ObjectExtensions - { - public static string PrintToString(this T obj) - { - return ObjectPrinter.For().PrintToString(obj); - } - } -} \ No newline at end of file diff --git a/ObjectPrinting/Solved/ObjectPrinter.cs b/ObjectPrinting/Solved/ObjectPrinter.cs deleted file mode 100644 index 540ee769..00000000 --- a/ObjectPrinting/Solved/ObjectPrinter.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace ObjectPrinting.Solved -{ - public class ObjectPrinter - { - public static PrintingConfig For() - { - return new PrintingConfig(); - } - } -} \ No newline at end of file diff --git a/ObjectPrinting/Solved/PrintingConfig.cs b/ObjectPrinting/Solved/PrintingConfig.cs deleted file mode 100644 index 0ec5aeb2..00000000 --- a/ObjectPrinting/Solved/PrintingConfig.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Linq; -using System.Linq.Expressions; -using System.Text; - -namespace ObjectPrinting.Solved -{ - public class PrintingConfig - { - public PropertyPrintingConfig Printing() - { - return new PropertyPrintingConfig(this); - } - - public PropertyPrintingConfig Printing(Expression> memberSelector) - { - return new PropertyPrintingConfig(this); - } - - public PrintingConfig Excluding(Expression> memberSelector) - { - return this; - } - - internal PrintingConfig Excluding() - { - return this; - } - - 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(); - } - } -} \ No newline at end of file diff --git a/ObjectPrinting/Solved/PropertyPrintingConfig.cs b/ObjectPrinting/Solved/PropertyPrintingConfig.cs deleted file mode 100644 index a509697d..00000000 --- a/ObjectPrinting/Solved/PropertyPrintingConfig.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Globalization; - -namespace ObjectPrinting.Solved -{ - public class PropertyPrintingConfig : IPropertyPrintingConfig - { - private readonly PrintingConfig printingConfig; - - public PropertyPrintingConfig(PrintingConfig printingConfig) - { - this.printingConfig = printingConfig; - } - - public PrintingConfig Using(Func print) - { - return printingConfig; - } - - public PrintingConfig Using(CultureInfo culture) - { - return printingConfig; - } - - PrintingConfig IPropertyPrintingConfig.ParentConfig => printingConfig; - } - - public interface IPropertyPrintingConfig - { - PrintingConfig ParentConfig { get; } - } -} \ No newline at end of file diff --git a/ObjectPrinting/Solved/PropertyPrintingConfigExtensions.cs b/ObjectPrinting/Solved/PropertyPrintingConfigExtensions.cs deleted file mode 100644 index dd392239..00000000 --- a/ObjectPrinting/Solved/PropertyPrintingConfigExtensions.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace ObjectPrinting.Solved -{ - public static class PropertyPrintingConfigExtensions - { - public static string PrintToString(this T obj, Func, PrintingConfig> config) - { - return config(ObjectPrinter.For()).PrintToString(obj); - } - - 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 deleted file mode 100644 index ac52d5ee..00000000 --- a/ObjectPrinting/Solved/Tests/ObjectPrinterAcceptanceTests.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Globalization; -using NUnit.Framework; - -namespace ObjectPrinting.Solved.Tests -{ - [TestFixture] - public class ObjectPrinterAcceptanceTests - { - [Test] - public void Demo() - { - var person = new Person { Name = "Alex", Age = 19 }; - - var printer = ObjectPrinter.For() - //1. Исключить из сериализации свойства определенного типа - .Excluding() - //2. Указать альтернативный способ сериализации для определенного типа - .Printing().Using(i => i.ToString("X")) - //3. Для числовых типов указать культуру - .Printing().Using(CultureInfo.InvariantCulture) - //4. Настроить сериализацию конкретного свойства - //5. Настроить обрезание строковых свойств (метод должен быть виден только для строковых свойств) - .Printing(p => p.Name).TrimmedToLength(10) - //6. Исключить из сериализации конкретного свойства - .Excluding(p => p.Age); - - string s1 = printer.PrintToString(person); - - //7. Синтаксический сахар в виде метода расширения, сериализующего по-умолчанию - string s2 = person.PrintToString(); - - //8. ...с конфигурированием - string s3 = person.PrintToString(s => s.Excluding(p => p.Age)); - Console.WriteLine(s1); - Console.WriteLine(s2); - Console.WriteLine(s3); - } - } -} \ No newline at end of file diff --git a/ObjectPrinting/Solved/Tests/Person.cs b/ObjectPrinting/Solved/Tests/Person.cs deleted file mode 100644 index 858ebbf8..00000000 --- a/ObjectPrinting/Solved/Tests/Person.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace ObjectPrinting.Solved.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 From 5153e7a2b200acb2895c47209f882df898f5a7be Mon Sep 17 00:00:00 2001 From: S4MPAI Date: Tue, 10 Dec 2024 01:46:23 +0500 Subject: [PATCH 02/12] add implementation for PrintingConfig.cs --- ObjectPrinting/ObjectPrinter.cs | 12 +- ObjectPrinting/ObjectPrinting.csproj | 1 + ObjectPrinting/ObjectSerializingExtensions.cs | 12 ++ ObjectPrinting/PrintingConfig.cs | 148 ++++++++++++++++-- ObjectPrinting/PropertyPrintingConfig.cs | 17 ++ .../PropertyPrintingConfigExtensions.cs | 15 ++ ObjectPrinting/TypePrintingConfig.cs | 17 ++ ObjectPrinting/TypePrintingExtensions.cs | 18 +++ fluent-api.sln.DotSettings | 3 + 9 files changed, 222 insertions(+), 21 deletions(-) create mode 100644 ObjectPrinting/ObjectSerializingExtensions.cs create mode 100644 ObjectPrinting/PropertyPrintingConfig.cs create mode 100644 ObjectPrinting/PropertyPrintingConfigExtensions.cs create mode 100644 ObjectPrinting/TypePrintingConfig.cs create mode 100644 ObjectPrinting/TypePrintingExtensions.cs diff --git a/ObjectPrinting/ObjectPrinter.cs b/ObjectPrinting/ObjectPrinter.cs index 3c7867c3..513af06c 100644 --- a/ObjectPrinting/ObjectPrinter.cs +++ b/ObjectPrinting/ObjectPrinter.cs @@ -1,10 +1,6 @@ -namespace ObjectPrinting +namespace ObjectPrinting; + +public static class ObjectPrinter { - public class ObjectPrinter - { - public static PrintingConfig For() - { - return new PrintingConfig(); - } - } + public static PrintingConfig For() => new(); } \ No newline at end of file diff --git a/ObjectPrinting/ObjectPrinting.csproj b/ObjectPrinting/ObjectPrinting.csproj index c5db392f..58e5743d 100644 --- a/ObjectPrinting/ObjectPrinting.csproj +++ b/ObjectPrinting/ObjectPrinting.csproj @@ -5,6 +5,7 @@ + diff --git a/ObjectPrinting/ObjectSerializingExtensions.cs b/ObjectPrinting/ObjectSerializingExtensions.cs new file mode 100644 index 00000000..82b6dcf5 --- /dev/null +++ b/ObjectPrinting/ObjectSerializingExtensions.cs @@ -0,0 +1,12 @@ +using System; + +namespace ObjectPrinting; + +public static class ObjectSerializingExtensions +{ + public static string PrintToString(this T obj) => + ObjectPrinter.For().PrintToString(obj); + + public static string PrintToString(this T obj, Func, PrintingConfig> printConfig) => + printConfig(ObjectPrinter.For()).PrintToString(obj); +} \ No newline at end of file diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index a9e08211..32dff858 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -1,41 +1,163 @@ using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; using System.Linq; +using System.Linq.Expressions; +using System.Reflection; using System.Text; namespace ObjectPrinting { public class PrintingConfig { - public string PrintToString(TOwner obj) + public Dictionary> TypeSerializers { get; } = []; + public Dictionary Cultures { get; } = []; + public Dictionary> PropertySerializers { get; } = []; + public Dictionary PropertiesMaxLength { get; } = []; + + private readonly Type[] primitiveTypes = + [ + typeof(int), + typeof(double), + typeof(float), + typeof(string), + typeof(DateTime), + typeof(TimeSpan) + ]; + private readonly HashSet excludingTypes = []; + private readonly HashSet excludingProperties = []; + + public PrintingConfig Excluding() + { + excludingTypes.Add(typeof(TPropertyType)); + + return this; + } + + public PrintingConfig Excluding(Expression> memberSelector) { - return PrintToString(obj, 0); + excludingProperties.Add(GetProperty(memberSelector)); + + return this; } - private string PrintToString(object obj, int nestingLevel) + public TypePrintingConfig For() => new(this); + + public PropertyPrintingConfig For(Expression> memberSelector) => + new(this, GetProperty(memberSelector)); + + public string PrintToString(TOwner obj) => + PrintToString(obj, 0, []); + + private string PrintToString(object obj, int nestingLevel, Dictionary parsedObjects) { - //TODO apply configurations if (obj == null) return "null" + Environment.NewLine; + + var type = obj.GetType(); + + if (primitiveTypes.Contains(type)) + return obj + Environment.NewLine; + + if (parsedObjects.TryGetValue(obj, out var level)) + return $"cycled {type.Name} in level {level}" + Environment.NewLine; + parsedObjects.Add(obj, nestingLevel); - var finalTypes = new[] + return obj switch { - typeof(int), typeof(double), typeof(float), typeof(string), - typeof(DateTime), typeof(TimeSpan) + IDictionary dictionary => PrintDictionary(dictionary, nestingLevel, parsedObjects), + IEnumerable collection => PrintCollection(collection, nestingLevel, parsedObjects), + _ => PrintClassProperties(obj, nestingLevel, parsedObjects) }; - if (finalTypes.Contains(obj.GetType())) - return obj + Environment.NewLine; + } + + private string PrintDictionary(IDictionary dictionary, int nestingLevel, Dictionary parsedObjects) + { + var sb = new StringBuilder(); + var nextNestingLevel = nestingLevel + 1; + var identation = new string('\t', nextNestingLevel); + sb.AppendLine("Dictionary"); + + foreach (DictionaryEntry kvp in dictionary) + { + var key = kvp.Key; + var value = kvp.Value!; + + sb.Append(identation + PrintToString(key, nestingLevel, parsedObjects).Trim() + + " : " + + PrintToString(value, nestingLevel, parsedObjects)); + } + + return sb.ToString(); + } - var identation = new string('\t', nestingLevel + 1); + private string PrintCollection(IEnumerable collection, int nestingLevel, Dictionary parsedObjects) + { var sb = new StringBuilder(); + var nextNestingLevel = nestingLevel + 1; + var identation = new string('\t', nextNestingLevel); + + sb.AppendLine("Collection"); + foreach (var element in collection) + sb.Append(identation + PrintToString(element, nextNestingLevel, parsedObjects)); + + return sb.ToString(); + } + + private string PrintClassProperties(object obj, int nestingLevel, Dictionary parsedObjects) + { var type = obj.GetType(); + var sb = new StringBuilder(); + var nextNestingLevel = nestingLevel + 1; + var identation = new string('\t', nextNestingLevel); + sb.AppendLine(type.Name); foreach (var propertyInfo in type.GetProperties()) { - sb.Append(identation + propertyInfo.Name + " = " + - PrintToString(propertyInfo.GetValue(obj), - nestingLevel + 1)); + if (excludingProperties.Contains(propertyInfo) || excludingTypes.Contains(propertyInfo.PropertyType)) + continue; + sb.Append(identation + + propertyInfo.Name + + " = " + + PrintProperty(obj, propertyInfo, nextNestingLevel, parsedObjects)); } + return sb.ToString(); } + + private PropertyInfo GetProperty(Expression> memberSelector) + { + if (memberSelector.Body is not MemberExpression memberExpression) + throw new ArgumentException($"Expression refers to a method, not a property."); + + return (memberExpression.Member as PropertyInfo)!; + } + + private string PrintProperty( + object obj, + PropertyInfo propertyInfo, + int nextNestingLevel, + Dictionary parsedObjects) + { + string? result = null; + var propertyValue = propertyInfo.GetValue(obj)!; + + if (PropertySerializers.TryGetValue(propertyInfo, out var propertySerializer)) + result = propertySerializer(propertyValue); + else if (TypeSerializers.TryGetValue(propertyInfo.PropertyType, out var typeSerializer)) + result = typeSerializer(propertyValue); + else if (PropertiesMaxLength.TryGetValue(propertyInfo, out var maxLength)) + { + var propertyString = (propertyValue as string)!; + result = propertyString[..Math.Min(propertyString.Length, maxLength)]; + } + else if (Cultures.TryGetValue(propertyInfo.PropertyType, out var culture)) + result = string.Format(culture, "{0}", propertyValue); + + return result == null ? + PrintToString(propertyValue, nextNestingLevel, parsedObjects) : + result + Environment.NewLine; + } } } \ No newline at end of file diff --git a/ObjectPrinting/PropertyPrintingConfig.cs b/ObjectPrinting/PropertyPrintingConfig.cs new file mode 100644 index 00000000..57b1751e --- /dev/null +++ b/ObjectPrinting/PropertyPrintingConfig.cs @@ -0,0 +1,17 @@ +using System; +using System.Reflection; + +namespace ObjectPrinting; + +public class PropertyPrintingConfig(PrintingConfig headConfig, PropertyInfo propertyInfo) +{ + public PrintingConfig HeadConfig => headConfig; + public PropertyInfo PropertyInfo => propertyInfo; + + public PrintingConfig Using(Func printing) + { + HeadConfig.PropertySerializers[propertyInfo] = p => printing((TProperty)p); + + return HeadConfig; + } +} \ No newline at end of file diff --git a/ObjectPrinting/PropertyPrintingConfigExtensions.cs b/ObjectPrinting/PropertyPrintingConfigExtensions.cs new file mode 100644 index 00000000..4d729289 --- /dev/null +++ b/ObjectPrinting/PropertyPrintingConfigExtensions.cs @@ -0,0 +1,15 @@ +namespace ObjectPrinting; + +public static class PropertyPrintingConfigExtensions +{ + public static PrintingConfig MaxLength( + this PropertyPrintingConfig propertyPrintingConfig, + int maxLen) + { + var headConfig = propertyPrintingConfig.HeadConfig; + + headConfig.PropertiesMaxLength[propertyPrintingConfig.PropertyInfo] = maxLen; + + return headConfig; + } +} \ No newline at end of file diff --git a/ObjectPrinting/TypePrintingConfig.cs b/ObjectPrinting/TypePrintingConfig.cs new file mode 100644 index 00000000..fd66895b --- /dev/null +++ b/ObjectPrinting/TypePrintingConfig.cs @@ -0,0 +1,17 @@ +using System; +using System.Globalization; + +namespace ObjectPrinting; + +public class TypePrintingConfig(PrintingConfig headConfig) +{ + public PrintingConfig HeadConfig { get; } = headConfig; + + public PrintingConfig Using(Func printing) + { + HeadConfig.TypeSerializers[typeof(TPropertyType)] = p => printing((TPropertyType)p); + + return HeadConfig; + } +} + diff --git a/ObjectPrinting/TypePrintingExtensions.cs b/ObjectPrinting/TypePrintingExtensions.cs new file mode 100644 index 00000000..2b177ae8 --- /dev/null +++ b/ObjectPrinting/TypePrintingExtensions.cs @@ -0,0 +1,18 @@ +using System; +using System.Globalization; + +namespace ObjectPrinting; + +public static class TypePrintingExtensions +{ + public static PrintingConfig Using( + this TypePrintingConfig config, + CultureInfo cultureInfo) where T : IFormattable + { + var headConfig = config.HeadConfig; + + headConfig.Cultures[typeof(T)] = cultureInfo; + + return headConfig; + } +} \ No newline at end of file diff --git a/fluent-api.sln.DotSettings b/fluent-api.sln.DotSettings index 135b83ec..229f449d 100644 --- a/fluent-api.sln.DotSettings +++ b/fluent-api.sln.DotSettings @@ -1,6 +1,9 @@  <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /> + <Policy><Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"><ElementKinds><Kind Name="FIELD" /><Kind Name="READONLY_FIELD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Types and namespaces"><ElementKinds><Kind Name="NAMESPACE" /><Kind Name="CLASS" /><Kind Name="STRUCT" /><Kind Name="ENUM" /><Kind Name="DELEGATE" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb_AaBb" /></Policy> + True True True Imported 10.10.2016 From d8a829486d4aca9ce005cc79f0819fae873091db Mon Sep 17 00:00:00 2001 From: S4MPAI Date: Tue, 10 Dec 2024 01:46:59 +0500 Subject: [PATCH 03/12] add tests for ObjectPrinter --- .../Tests/ObjectPrinterAcceptanceTests.cs | 18 +- ObjectPrinting/Tests/ObjectPrinterTests.cs | 160 ++++++++++++++++++ ObjectPrinting/Tests/PersonWithParent.cs | 12 ++ ObjectPrinting/Tests/PersonWithWeight.cs | 12 ++ 4 files changed, 198 insertions(+), 4 deletions(-) create mode 100644 ObjectPrinting/Tests/ObjectPrinterTests.cs create mode 100644 ObjectPrinting/Tests/PersonWithParent.cs create mode 100644 ObjectPrinting/Tests/PersonWithWeight.cs diff --git a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs index 4c8b2445..8c922800 100644 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs @@ -1,4 +1,6 @@ -using NUnit.Framework; +using System; +using System.Globalization; +using NUnit.Framework; namespace ObjectPrinting.Tests { @@ -10,18 +12,26 @@ public void Demo() { var person = new Person { Name = "Alex", Age = 19 }; - var printer = ObjectPrinter.For(); + var printer = ObjectPrinter.For() //1. Исключить из сериализации свойства определенного типа + .Excluding() //2. Указать альтернативный способ сериализации для определенного типа + .For().Using(i => i.ToString()) //3. Для числовых типов указать культуру + .For().Using(CultureInfo.CurrentCulture) //4. Настроить сериализацию конкретного свойства + .For(p => p.Age).Using(age => age.ToString()) //5. Настроить обрезание строковых свойств (метод должен быть виден только для строковых свойств) + .For(p => p.Name).MaxLength(10) //6. Исключить из сериализации конкретного свойства + .Excluding(x => x.Name); - string s1 = printer.PrintToString(person); + var s1 = printer.PrintToString(person); - //7. Синтаксический сахар в виде метода расширения, сериализующего по-умолчанию + //7. Синтаксический сахар в виде метода расширения, сериализующего по-умолчанию + var s2 = person.PrintToString(); //8. ...с конфигурированием + var s3 = person.PrintToString(config => config); } } } \ No newline at end of file diff --git a/ObjectPrinting/Tests/ObjectPrinterTests.cs b/ObjectPrinting/Tests/ObjectPrinterTests.cs new file mode 100644 index 00000000..46780447 --- /dev/null +++ b/ObjectPrinting/Tests/ObjectPrinterTests.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using FluentAssertions; +using NUnit.Framework; + +namespace ObjectPrinting.Tests; + +[TestFixture] +public class ObjectPrinterTests +{ + [Test] + public void PrintToString_ShouldReturnSerializedPerson_WithAllProperties() + { + var person = new Person { Name = "John", Age = 25, Height = 175}; + + var actualResult = ObjectPrinter.For().PrintToString(person); + var expectedResult = "Person\r\n\tId = Guid\r\n\tName = John\r\n\tHeight = 175\r\n\tAge = 25\r\n"; + + actualResult.Should().BeEquivalentTo(expectedResult); + } + + [Test] + public void PrintToString_ShouldReturnSerializedPerson_WithExcludedDouble() + { + var personWithWeight = new PersonWithWeight { Name = "John", Age = 25, Height = 175, Weight = 70 }; + + var actualResult = ObjectPrinter.For().Excluding().PrintToString(personWithWeight); + var expectedResult = "PersonWithWeight\r\n\tId = Guid\r\n\tName = John\r\n\tAge = 25\r\n"; + + actualResult.Should().BeEquivalentTo(expectedResult); + } + + [Test] + public void PrintToString_ShouldReturnSerializedPerson_WithExcludedId() + { + var person = new Person { Name = "John", Age = 25, Height = 175 }; + + var actualResult = ObjectPrinter.For().Excluding(p => p.Id).PrintToString(person); + var expectedResult = "Person\r\n\tName = John\r\n\tHeight = 175\r\n\tAge = 25\r\n"; + + actualResult.Should().BeEquivalentTo(expectedResult); + } + + [Test] + public void PrintToString_ShouldReturnSerializedPerson_WithSerializationForType() + { + var personWithWeight = new PersonWithWeight { Name = "John", Age = 25, Height = 175, Weight = 70 }; + + var actualResult = ObjectPrinter + .For() + .For().Using(x => $"{x:F2}") + .PrintToString(personWithWeight); + var expectedResult = "PersonWithWeight\r\n" + + "\tId = Guid\r\n" + + "\tName = John\r\n" + + "\tHeight = 175,00\r\n" + + "\tWeight = 70,00\r\n" + + "\tAge = 25\r\n"; + + actualResult.Should().BeEquivalentTo(expectedResult); + } + + [Test] + public void PrintToString_ShouldReturnSerializedPerson_WithCultureInfo() + { + var personWithWeight = new PersonWithWeight { Name = "John", Age = 25, Height = 175.5, Weight = 70.5 }; + + var actualResult = ObjectPrinter + .For() + .For().Using(CultureInfo.InvariantCulture) + .PrintToString(personWithWeight); + var expectedResult = "PersonWithWeight\r\n" + + "\tId = Guid\r\n" + + "\tName = John\r\n" + + "\tHeight = 175.5\r\n" + + "\tWeight = 70.5\r\n" + + "\tAge = 25\r\n"; + + actualResult.Should().BeEquivalentTo(expectedResult); + } + + [Test] + public void PrintToString_ShouldReturnSerializedPerson_WithSerializationForProperty() + { + var person = new Person { Name = "John", Age = 25, Height = 175.6 }; + + var actualResult = ObjectPrinter + .For() + .For(p => p.Height).Using(h => ((int)Math.Round(h)).ToString()) + .PrintToString(person); + var expectedResult = "Person\r\n\tId = Guid\r\n\tName = John\r\n\tHeight = 176\r\n\tAge = 25\r\n"; + + actualResult.Should().BeEquivalentTo(expectedResult); + } + + [Test] + public void PrintToString_ShouldReturnSerializedPerson_WithStringTrim() + { + var person = new Person { Name = "John Jo", Age = 25, Height = 175 }; + + var actualResult = ObjectPrinter + .For() + .For(p => p.Name).MaxLength(4) + .PrintToString(person); + var expectedResult = "Person\r\n\tId = Guid\r\n\tName = John\r\n\tHeight = 175\r\n\tAge = 25\r\n"; + + actualResult.Should().BeEquivalentTo(expectedResult); + } + + [Test] + public void PrintToString_ShouldReturnSerializedPerson_WithCycleReference() + { + var personWithParent = new PersonWithParent { Name = "John", Age = 25, Height = 175 }; + personWithParent.Parent = personWithParent; + + var actualResult = ObjectPrinter + .For() + .PrintToString(personWithParent); + var expectedResult = "PersonWithParent\r\n" + + "\tId = Guid\r\n" + + "\tName = John\r\n" + + "\tHeight = 175\r\n" + + "\tAge = 25\r\n" + + "\tParent = cycled PersonWithParent in level 0\r\n"; + + actualResult.Should().BeEquivalentTo(expectedResult); + } + + [Test] + public void PrintToString_ShouldReturnSerializedList() + { + var numbers = new[] { 1, 2, 3, 4 }; + + var actualResult = ObjectPrinter + .For() + .PrintToString(numbers); + var expectedResult = "Collection\r\n\t1\r\n\t2\r\n\t3\r\n\t4\r\n"; + + actualResult.Should().BeEquivalentTo(expectedResult); + } + + [Test] + public void PrintToString_ShouldReturnSerializedDictionary() + { + var dictionary = new Dictionary + { + { 1, "test1" }, + { 2, "test2" }, + { 3, "test3" } + }; + + var actualResult = ObjectPrinter + .For>() + .PrintToString(dictionary); + var expectedResult = "Dictionary\r\n\t1 : test1\r\n\t2 : test2\r\n\t3 : test3\r\n"; + + actualResult.Should().BeEquivalentTo(expectedResult); + } +} \ No newline at end of file diff --git a/ObjectPrinting/Tests/PersonWithParent.cs b/ObjectPrinting/Tests/PersonWithParent.cs new file mode 100644 index 00000000..75bb1369 --- /dev/null +++ b/ObjectPrinting/Tests/PersonWithParent.cs @@ -0,0 +1,12 @@ +using System; + +namespace ObjectPrinting.Tests; + +public class PersonWithParent +{ + public Guid Id { get; set; } + public string Name { get; set; } + public double Height { get; set; } + public int Age { get; set; } + public PersonWithParent Parent { get; set; } +} \ No newline at end of file diff --git a/ObjectPrinting/Tests/PersonWithWeight.cs b/ObjectPrinting/Tests/PersonWithWeight.cs new file mode 100644 index 00000000..b1310110 --- /dev/null +++ b/ObjectPrinting/Tests/PersonWithWeight.cs @@ -0,0 +1,12 @@ +using System; + +namespace ObjectPrinting.Tests; + +public class PersonWithWeight +{ + public Guid Id { get; set; } + public string Name { get; set; } + public double Height { get; set; } + public double Weight { get; set; } + public int Age { get; set; } +} \ No newline at end of file From be6059d5c099e2060a87625420f2210d003b16a0 Mon Sep 17 00:00:00 2001 From: S4MPAI Date: Sat, 14 Dec 2024 18:22:58 +0500 Subject: [PATCH 04/12] moved ObjectPrintingTests in test project --- ObjectPrinting/ObjectPrinting.csproj | 7 ----- fluent-api.sln | 9 ++++++ .../ObjectPrinterAcceptanceTests.cs | 7 ++--- .../ObjectPrinterTests.cs | 6 ++-- .../ObjectPrintingTests.csproj | 29 +++++++++++++++++++ .../ObjectPrintingTests}/Person.cs | 4 +-- .../ObjectPrintingTests}/PersonWithParent.cs | 4 +-- .../ObjectPrintingTests}/PersonWithWeight.cs | 4 +-- 8 files changed, 46 insertions(+), 24 deletions(-) rename {ObjectPrinting/Tests => tests/ObjectPrintingTests}/ObjectPrinterAcceptanceTests.cs (94%) rename {ObjectPrinting/Tests => tests/ObjectPrintingTests}/ObjectPrinterTests.cs (98%) create mode 100644 tests/ObjectPrintingTests/ObjectPrintingTests.csproj rename {ObjectPrinting/Tests => tests/ObjectPrintingTests}/Person.cs (80%) rename {ObjectPrinting/Tests => tests/ObjectPrintingTests}/PersonWithParent.cs (82%) rename {ObjectPrinting/Tests => tests/ObjectPrintingTests}/PersonWithWeight.cs (82%) diff --git a/ObjectPrinting/ObjectPrinting.csproj b/ObjectPrinting/ObjectPrinting.csproj index 58e5743d..6a9fd13d 100644 --- a/ObjectPrinting/ObjectPrinting.csproj +++ b/ObjectPrinting/ObjectPrinting.csproj @@ -3,11 +3,4 @@ net8.0 enable - - - - - - - diff --git a/fluent-api.sln b/fluent-api.sln index 69c8db9e..35f28340 100644 --- a/fluent-api.sln +++ b/fluent-api.sln @@ -13,6 +13,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentMapping.Tests", "Samp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spectacle", "Samples\Spectacle\Spectacle.csproj", "{EFA9335C-411B-4597-B0B6-5438D1AE04C3}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{E4AEC989-D540-44CF-8896-23C7DC04CB4C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObjectPrintingTests", "tests\ObjectPrintingTests\ObjectPrintingTests.csproj", "{71311FE6-B67B-4E3C-A076-3FF03A745629}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -35,6 +39,10 @@ Global {EFA9335C-411B-4597-B0B6-5438D1AE04C3}.Debug|Any CPU.Build.0 = Debug|Any CPU {EFA9335C-411B-4597-B0B6-5438D1AE04C3}.Release|Any CPU.ActiveCfg = Release|Any CPU {EFA9335C-411B-4597-B0B6-5438D1AE04C3}.Release|Any CPU.Build.0 = Release|Any CPU + {71311FE6-B67B-4E3C-A076-3FF03A745629}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71311FE6-B67B-4E3C-A076-3FF03A745629}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71311FE6-B67B-4E3C-A076-3FF03A745629}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71311FE6-B67B-4E3C-A076-3FF03A745629}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -43,5 +51,6 @@ Global {FEEA5AFE-459A-4D13-81D0-252E1A2E6F4E} = {6D308E4A-CEC7-4536-9B87-81CD337A87AD} {8A7BB3EA-3E6A-4D04-A801-D5CD1620DA0D} = {6D308E4A-CEC7-4536-9B87-81CD337A87AD} {EFA9335C-411B-4597-B0B6-5438D1AE04C3} = {6D308E4A-CEC7-4536-9B87-81CD337A87AD} + {71311FE6-B67B-4E3C-A076-3FF03A745629} = {E4AEC989-D540-44CF-8896-23C7DC04CB4C} EndGlobalSection EndGlobal diff --git a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/tests/ObjectPrintingTests/ObjectPrinterAcceptanceTests.cs similarity index 94% rename from ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs rename to tests/ObjectPrintingTests/ObjectPrinterAcceptanceTests.cs index 8c922800..9d357859 100644 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ b/tests/ObjectPrintingTests/ObjectPrinterAcceptanceTests.cs @@ -1,8 +1,7 @@ -using System; -using System.Globalization; -using NUnit.Framework; +using System.Globalization; +using ObjectPrinting; -namespace ObjectPrinting.Tests +namespace ObjectPrintingTests { [TestFixture] public class ObjectPrinterAcceptanceTests diff --git a/ObjectPrinting/Tests/ObjectPrinterTests.cs b/tests/ObjectPrintingTests/ObjectPrinterTests.cs similarity index 98% rename from ObjectPrinting/Tests/ObjectPrinterTests.cs rename to tests/ObjectPrintingTests/ObjectPrinterTests.cs index 46780447..02c1aac8 100644 --- a/ObjectPrinting/Tests/ObjectPrinterTests.cs +++ b/tests/ObjectPrintingTests/ObjectPrinterTests.cs @@ -1,10 +1,8 @@ -using System; -using System.Collections.Generic; using System.Globalization; using FluentAssertions; -using NUnit.Framework; +using ObjectPrinting; -namespace ObjectPrinting.Tests; +namespace ObjectPrintingTests; [TestFixture] public class ObjectPrinterTests diff --git a/tests/ObjectPrintingTests/ObjectPrintingTests.csproj b/tests/ObjectPrintingTests/ObjectPrintingTests.csproj new file mode 100644 index 00000000..2d570d73 --- /dev/null +++ b/tests/ObjectPrintingTests/ObjectPrintingTests.csproj @@ -0,0 +1,29 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + + + + diff --git a/ObjectPrinting/Tests/Person.cs b/tests/ObjectPrintingTests/Person.cs similarity index 80% rename from ObjectPrinting/Tests/Person.cs rename to tests/ObjectPrintingTests/Person.cs index f9555955..977c7eb8 100644 --- a/ObjectPrinting/Tests/Person.cs +++ b/tests/ObjectPrintingTests/Person.cs @@ -1,6 +1,4 @@ -using System; - -namespace ObjectPrinting.Tests +namespace ObjectPrintingTests { public class Person { diff --git a/ObjectPrinting/Tests/PersonWithParent.cs b/tests/ObjectPrintingTests/PersonWithParent.cs similarity index 82% rename from ObjectPrinting/Tests/PersonWithParent.cs rename to tests/ObjectPrintingTests/PersonWithParent.cs index 75bb1369..38693453 100644 --- a/ObjectPrinting/Tests/PersonWithParent.cs +++ b/tests/ObjectPrintingTests/PersonWithParent.cs @@ -1,6 +1,4 @@ -using System; - -namespace ObjectPrinting.Tests; +namespace ObjectPrintingTests; public class PersonWithParent { diff --git a/ObjectPrinting/Tests/PersonWithWeight.cs b/tests/ObjectPrintingTests/PersonWithWeight.cs similarity index 82% rename from ObjectPrinting/Tests/PersonWithWeight.cs rename to tests/ObjectPrintingTests/PersonWithWeight.cs index b1310110..3aabbdb8 100644 --- a/ObjectPrinting/Tests/PersonWithWeight.cs +++ b/tests/ObjectPrintingTests/PersonWithWeight.cs @@ -1,6 +1,4 @@ -using System; - -namespace ObjectPrinting.Tests; +namespace ObjectPrintingTests; public class PersonWithWeight { From 704e24352e2c84ff808e3da0cd9a5b8e27469120 Mon Sep 17 00:00:00 2001 From: S4MPAI Date: Sun, 15 Dec 2024 00:16:00 +0500 Subject: [PATCH 05/12] take out member serializing logic in IMembersSerializer.cs implementations --- ObjectPrinting/Helpers/MemberHelper.cs | 42 +++++++++++ ObjectPrinting/PrintingConfig.cs | 74 +++++++++---------- ObjectPrinting/PropertyPrintingConfig.cs | 10 ++- .../PropertyPrintingConfigExtensions.cs | 16 +++- .../Serializers/BaseMembersSerializer.cs | 21 ++++++ .../Serializers/IMembersSerializer.cs | 8 ++ .../Serializers/MembersSerializerByMember.cs | 25 +++++++ .../Serializers/MembersSerializerByType.cs | 25 +++++++ ObjectPrinting/TypePrintingConfig.cs | 7 +- ObjectPrinting/TypePrintingExtensions.cs | 6 +- 10 files changed, 187 insertions(+), 47 deletions(-) create mode 100644 ObjectPrinting/Helpers/MemberHelper.cs create mode 100644 ObjectPrinting/Serializers/BaseMembersSerializer.cs create mode 100644 ObjectPrinting/Serializers/IMembersSerializer.cs create mode 100644 ObjectPrinting/Serializers/MembersSerializerByMember.cs create mode 100644 ObjectPrinting/Serializers/MembersSerializerByType.cs diff --git a/ObjectPrinting/Helpers/MemberHelper.cs b/ObjectPrinting/Helpers/MemberHelper.cs new file mode 100644 index 00000000..2ec5ce54 --- /dev/null +++ b/ObjectPrinting/Helpers/MemberHelper.cs @@ -0,0 +1,42 @@ +using System; +using System.Reflection; + +namespace ObjectPrinting.Helpers; + +public static class MemberHelper +{ + public static bool TryGetMemberValue(object declaringObj, MemberInfo memberInfo, out object value) + { + value = null!; + if (!TryGetTypeAndValueOfMember(declaringObj, memberInfo, out var memberData)) + return false; + + value = memberData!.Value.memberValue; + return true; + } + + public static bool TryGetMemberType(object declaringObj, MemberInfo memberInfo, out Type type) + { + type = null!; + if (!TryGetTypeAndValueOfMember(declaringObj, memberInfo, out var memberData)) + return false; + + type = memberData!.Value.memberType; + return true; + } + + public static bool TryGetTypeAndValueOfMember( + object declaringObj, + MemberInfo memberInfo, + out (object memberValue, Type memberType)? memberData) + { + memberData = memberInfo switch + { + PropertyInfo propertyInfo => (propertyInfo.GetValue(declaringObj)!, propertyInfo.PropertyType), + FieldInfo fieldInfo => (fieldInfo.GetValue(declaringObj)!, fieldInfo.FieldType), + _ => null + }; + + return memberData != null; + } +} \ No newline at end of file diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 32dff858..267755b5 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -1,32 +1,31 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; +using ObjectPrinting.Helpers; +using ObjectPrinting.Serializers; namespace ObjectPrinting { public class PrintingConfig { - public Dictionary> TypeSerializers { get; } = []; - public Dictionary Cultures { get; } = []; - public Dictionary> PropertySerializers { get; } = []; - public Dictionary PropertiesMaxLength { get; } = []; + internal readonly IMembersSerializer[] MembersSerializers = + [ + new MembersSerializerByMember(), + new MembersSerializerByType() + ]; - private readonly Type[] primitiveTypes = + private readonly HashSet primitiveTypes = [ - typeof(int), - typeof(double), - typeof(float), typeof(string), typeof(DateTime), typeof(TimeSpan) ]; private readonly HashSet excludingTypes = []; - private readonly HashSet excludingProperties = []; + private readonly HashSet excludingProperties = []; public PrintingConfig Excluding() { @@ -37,7 +36,7 @@ public PrintingConfig Excluding() public PrintingConfig Excluding(Expression> memberSelector) { - excludingProperties.Add(GetProperty(memberSelector)); + excludingProperties.Add(GetMember(memberSelector)); return this; } @@ -45,7 +44,7 @@ public PrintingConfig Excluding(Expression For() => new(this); public PropertyPrintingConfig For(Expression> memberSelector) => - new(this, GetProperty(memberSelector)); + new(this, GetMember(memberSelector)); public string PrintToString(TOwner obj) => PrintToString(obj, 0, []); @@ -57,7 +56,7 @@ private string PrintToString(object obj, int nestingLevel, Dictionary m.MemberType is MemberTypes.Property or MemberTypes.Field).ToList(); + foreach (var memberInfo in neededMembers) { - if (excludingProperties.Contains(propertyInfo) || excludingTypes.Contains(propertyInfo.PropertyType)) + MemberHelper.TryGetMemberType(obj, memberInfo, out var memberType); + if (excludingProperties.Contains(memberInfo) || excludingTypes.Contains(memberType)) continue; + sb.Append(identation + - propertyInfo.Name + + memberInfo.Name + " = " + - PrintProperty(obj, propertyInfo, nextNestingLevel, parsedObjects)); + PrintMember(obj, memberInfo, nextNestingLevel, parsedObjects)); } return sb.ToString(); } - private PropertyInfo GetProperty(Expression> memberSelector) + private MemberInfo GetMember(Expression> memberSelector) { if (memberSelector.Body is not MemberExpression memberExpression) - throw new ArgumentException($"Expression refers to a method, not a property."); + throw new ArgumentException("Expression refers to a method, not a property."); - return (memberExpression.Member as PropertyInfo)!; + return memberExpression.Member; } - private string PrintProperty( + private string PrintMember( object obj, - PropertyInfo propertyInfo, + MemberInfo memberInfo, int nextNestingLevel, Dictionary parsedObjects) { string? result = null; - var propertyValue = propertyInfo.GetValue(obj)!; - - if (PropertySerializers.TryGetValue(propertyInfo, out var propertySerializer)) - result = propertySerializer(propertyValue); - else if (TypeSerializers.TryGetValue(propertyInfo.PropertyType, out var typeSerializer)) - result = typeSerializer(propertyValue); - else if (PropertiesMaxLength.TryGetValue(propertyInfo, out var maxLength)) - { - var propertyString = (propertyValue as string)!; - result = propertyString[..Math.Min(propertyString.Length, maxLength)]; - } - else if (Cultures.TryGetValue(propertyInfo.PropertyType, out var culture)) - result = string.Format(culture, "{0}", propertyValue); + + foreach (var serializer in MembersSerializers) + if (serializer.TrySerialize(obj, memberInfo, out result)) + break; - return result == null ? - PrintToString(propertyValue, nextNestingLevel, parsedObjects) : - result + Environment.NewLine; + MemberHelper.TryGetMemberValue(obj, memberInfo, out var propertyValue); + return result == null + ? PrintToString(propertyValue, nextNestingLevel, parsedObjects) + : result + Environment.NewLine; } } } \ No newline at end of file diff --git a/ObjectPrinting/PropertyPrintingConfig.cs b/ObjectPrinting/PropertyPrintingConfig.cs index 57b1751e..c16722e8 100644 --- a/ObjectPrinting/PropertyPrintingConfig.cs +++ b/ObjectPrinting/PropertyPrintingConfig.cs @@ -1,16 +1,20 @@ using System; +using System.Linq; using System.Reflection; +using ObjectPrinting.Serializers; namespace ObjectPrinting; -public class PropertyPrintingConfig(PrintingConfig headConfig, PropertyInfo propertyInfo) +public class PropertyPrintingConfig(PrintingConfig headConfig, MemberInfo memberInfo) { public PrintingConfig HeadConfig => headConfig; - public PropertyInfo PropertyInfo => propertyInfo; + public MemberInfo PropertyInfo => memberInfo; public PrintingConfig Using(Func printing) { - HeadConfig.PropertySerializers[propertyInfo] = p => printing((TProperty)p); + ((MembersSerializerByMember)HeadConfig.MembersSerializers + .First(x => x is MembersSerializerByMember)) + .SerializerRules[PropertyInfo] = p => printing((TProperty)p); return HeadConfig; } diff --git a/ObjectPrinting/PropertyPrintingConfigExtensions.cs b/ObjectPrinting/PropertyPrintingConfigExtensions.cs index 4d729289..0f0a4611 100644 --- a/ObjectPrinting/PropertyPrintingConfigExtensions.cs +++ b/ObjectPrinting/PropertyPrintingConfigExtensions.cs @@ -1,15 +1,27 @@ +using System; +using System.Linq; +using ObjectPrinting.Serializers; + namespace ObjectPrinting; public static class PropertyPrintingConfigExtensions { public static PrintingConfig MaxLength( this PropertyPrintingConfig propertyPrintingConfig, - int maxLen) + int maxLength) { var headConfig = propertyPrintingConfig.HeadConfig; - headConfig.PropertiesMaxLength[propertyPrintingConfig.PropertyInfo] = maxLen; + ((MembersSerializerByMember)headConfig.MembersSerializers + .First(x => x is MembersSerializerByMember)) + .SerializerRules[propertyPrintingConfig.PropertyInfo] = x => TrimString(x, maxLength); return headConfig; } + + private static string TrimString(object value, int maxLength) + { + var propertyString = (value as string)!; + return propertyString[..Math.Min(propertyString.Length, maxLength)]; + } } \ No newline at end of file diff --git a/ObjectPrinting/Serializers/BaseMembersSerializer.cs b/ObjectPrinting/Serializers/BaseMembersSerializer.cs new file mode 100644 index 00000000..3fd8ec29 --- /dev/null +++ b/ObjectPrinting/Serializers/BaseMembersSerializer.cs @@ -0,0 +1,21 @@ +using System; +using System.Reflection; +using ObjectPrinting.Helpers; + +namespace ObjectPrinting.Serializers; + +public abstract class BaseMembersSerializer : IMembersSerializer +{ + public bool TrySerialize(object obj, MemberInfo memberInfo, out string result) + { + result = null!; + return MemberHelper.TryGetTypeAndValueOfMember(obj, memberInfo, out var memberData) && + TrySerializeProtected(memberData!.Value.memberValue, memberData.Value.memberType, memberInfo, out result); + } + + protected abstract bool TrySerializeProtected( + object memberValue, + Type memberType, + MemberInfo memberInfo, + out string serializedMemberInfo); +} \ No newline at end of file diff --git a/ObjectPrinting/Serializers/IMembersSerializer.cs b/ObjectPrinting/Serializers/IMembersSerializer.cs new file mode 100644 index 00000000..c8a89f9c --- /dev/null +++ b/ObjectPrinting/Serializers/IMembersSerializer.cs @@ -0,0 +1,8 @@ +using System.Reflection; + +namespace ObjectPrinting.Serializers; + +public interface IMembersSerializer +{ + public bool TrySerialize(object obj, MemberInfo memberInfo, out string result); +} \ No newline at end of file diff --git a/ObjectPrinting/Serializers/MembersSerializerByMember.cs b/ObjectPrinting/Serializers/MembersSerializerByMember.cs new file mode 100644 index 00000000..efb2033b --- /dev/null +++ b/ObjectPrinting/Serializers/MembersSerializerByMember.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace ObjectPrinting.Serializers; + +public class MembersSerializerByMember : BaseMembersSerializer +{ + public Dictionary> SerializerRules { get; } = new(); + + protected override bool TrySerializeProtected( + object memberValue, + Type memberType, + MemberInfo memberInfo, + out string serializedMemberInfo) + { + serializedMemberInfo = null!; + if (!SerializerRules.TryGetValue(memberInfo, out var rule)) + return false; + + serializedMemberInfo = rule(memberValue); + return true; + + } +} \ No newline at end of file diff --git a/ObjectPrinting/Serializers/MembersSerializerByType.cs b/ObjectPrinting/Serializers/MembersSerializerByType.cs new file mode 100644 index 00000000..f134cbb9 --- /dev/null +++ b/ObjectPrinting/Serializers/MembersSerializerByType.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace ObjectPrinting.Serializers; + +public class MembersSerializerByType : BaseMembersSerializer +{ + public Dictionary> SerializerRules { get; } = new(); + + protected override bool TrySerializeProtected( + object memberValue, + Type memberType, + MemberInfo memberInfo, + out string serializedMemberInfo) + { + serializedMemberInfo = null!; + if (!SerializerRules.TryGetValue(memberType, out var rule)) + return false; + + serializedMemberInfo = rule(memberValue); + return true; + + } +} \ No newline at end of file diff --git a/ObjectPrinting/TypePrintingConfig.cs b/ObjectPrinting/TypePrintingConfig.cs index fd66895b..74344951 100644 --- a/ObjectPrinting/TypePrintingConfig.cs +++ b/ObjectPrinting/TypePrintingConfig.cs @@ -1,5 +1,6 @@ using System; -using System.Globalization; +using System.Linq; +using ObjectPrinting.Serializers; namespace ObjectPrinting; @@ -9,7 +10,9 @@ public class TypePrintingConfig(PrintingConfig he public PrintingConfig Using(Func printing) { - HeadConfig.TypeSerializers[typeof(TPropertyType)] = p => printing((TPropertyType)p); + ((MembersSerializerByType)HeadConfig.MembersSerializers + .First(x => x is MembersSerializerByType)) + .SerializerRules[typeof(TPropertyType)] = p => printing((TPropertyType)p); return HeadConfig; } diff --git a/ObjectPrinting/TypePrintingExtensions.cs b/ObjectPrinting/TypePrintingExtensions.cs index 2b177ae8..42c946f0 100644 --- a/ObjectPrinting/TypePrintingExtensions.cs +++ b/ObjectPrinting/TypePrintingExtensions.cs @@ -1,5 +1,7 @@ using System; using System.Globalization; +using System.Linq; +using ObjectPrinting.Serializers; namespace ObjectPrinting; @@ -11,7 +13,9 @@ public static PrintingConfig Using( { var headConfig = config.HeadConfig; - headConfig.Cultures[typeof(T)] = cultureInfo; + ((MembersSerializerByType)headConfig.MembersSerializers + .First(x => x is MembersSerializerByType)) + .SerializerRules[typeof(T)] = x => string.Format(cultureInfo, "{0}", x); return headConfig; } From b63e36fb530e3cc4bf2fe8a272a6d39455b98088 Mon Sep 17 00:00:00 2001 From: S4MPAI Date: Sun, 15 Dec 2024 00:16:37 +0500 Subject: [PATCH 06/12] add new tests --- .../ObjectPrintingTests/ObjectPrinterTests.cs | 42 ++++++++++++++----- tests/ObjectPrintingTests/PersonWithFields.cs | 9 ++++ 2 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 tests/ObjectPrintingTests/PersonWithFields.cs diff --git a/tests/ObjectPrintingTests/ObjectPrinterTests.cs b/tests/ObjectPrintingTests/ObjectPrinterTests.cs index 02c1aac8..fe3e0524 100644 --- a/tests/ObjectPrintingTests/ObjectPrinterTests.cs +++ b/tests/ObjectPrintingTests/ObjectPrinterTests.cs @@ -8,7 +8,7 @@ namespace ObjectPrintingTests; public class ObjectPrinterTests { [Test] - public void PrintToString_ShouldReturnSerializedPerson_WithAllProperties() + public void PrintToString_ShouldSerializePerson_WhenUseProperties() { var person = new Person { Name = "John", Age = 25, Height = 175}; @@ -19,7 +19,18 @@ public void PrintToString_ShouldReturnSerializedPerson_WithAllProperties() } [Test] - public void PrintToString_ShouldReturnSerializedPerson_WithExcludedDouble() + public void PrintToString_ShouldSerializePerson_WhenUseFields() + { + var person = new PersonWithFields { Name = "John", Age = 25, Height = 175}; + + var actualResult = ObjectPrinter.For().PrintToString(person); + var expectedResult = "PersonWithFields\r\n\tId = Guid\r\n\tName = John\r\n\tHeight = 175\r\n\tAge = 25\r\n"; + + actualResult.Should().BeEquivalentTo(expectedResult); + } + + [Test] + public void PrintToString_ShouldSerializePerson_WhenExcludeType() { var personWithWeight = new PersonWithWeight { Name = "John", Age = 25, Height = 175, Weight = 70 }; @@ -30,7 +41,7 @@ public void PrintToString_ShouldReturnSerializedPerson_WithExcludedDouble() } [Test] - public void PrintToString_ShouldReturnSerializedPerson_WithExcludedId() + public void PrintToString_ShouldSerializePerson_WhenExcludeProperty() { var person = new Person { Name = "John", Age = 25, Height = 175 }; @@ -41,7 +52,18 @@ public void PrintToString_ShouldReturnSerializedPerson_WithExcludedId() } [Test] - public void PrintToString_ShouldReturnSerializedPerson_WithSerializationForType() + public void PrintToString_ShouldSerializePerson_WhenExcludeFields() + { + var person = new PersonWithFields { Name = "John", Age = 25, Height = 175 }; + + var actualResult = ObjectPrinter.For().Excluding(p => p.Id).PrintToString(person); + var expectedResult = "PersonWithFields\r\n\tName = John\r\n\tHeight = 175\r\n\tAge = 25\r\n"; + + actualResult.Should().BeEquivalentTo(expectedResult); + } + + [Test] + public void PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForType() { var personWithWeight = new PersonWithWeight { Name = "John", Age = 25, Height = 175, Weight = 70 }; @@ -60,7 +82,7 @@ public void PrintToString_ShouldReturnSerializedPerson_WithSerializationForType( } [Test] - public void PrintToString_ShouldReturnSerializedPerson_WithCultureInfo() + public void PrintToString_ShouldSerializePerson_WhenUseCustomCultureInfo() { var personWithWeight = new PersonWithWeight { Name = "John", Age = 25, Height = 175.5, Weight = 70.5 }; @@ -79,7 +101,7 @@ public void PrintToString_ShouldReturnSerializedPerson_WithCultureInfo() } [Test] - public void PrintToString_ShouldReturnSerializedPerson_WithSerializationForProperty() + public void PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForMember() { var person = new Person { Name = "John", Age = 25, Height = 175.6 }; @@ -93,7 +115,7 @@ public void PrintToString_ShouldReturnSerializedPerson_WithSerializationForPrope } [Test] - public void PrintToString_ShouldReturnSerializedPerson_WithStringTrim() + public void PrintToString_ShouldSerializePerson_WhenTrimString() { var person = new Person { Name = "John Jo", Age = 25, Height = 175 }; @@ -107,7 +129,7 @@ public void PrintToString_ShouldReturnSerializedPerson_WithStringTrim() } [Test] - public void PrintToString_ShouldReturnSerializedPerson_WithCycleReference() + public void PrintToString_ShouldSerializePerson_WhenHaveCycleReference() { var personWithParent = new PersonWithParent { Name = "John", Age = 25, Height = 175 }; personWithParent.Parent = personWithParent; @@ -126,7 +148,7 @@ public void PrintToString_ShouldReturnSerializedPerson_WithCycleReference() } [Test] - public void PrintToString_ShouldReturnSerializedList() + public void PrintToString_ShouldSerializeList() { var numbers = new[] { 1, 2, 3, 4 }; @@ -139,7 +161,7 @@ public void PrintToString_ShouldReturnSerializedList() } [Test] - public void PrintToString_ShouldReturnSerializedDictionary() + public void PrintToString_ShouldSerializeDictionary() { var dictionary = new Dictionary { diff --git a/tests/ObjectPrintingTests/PersonWithFields.cs b/tests/ObjectPrintingTests/PersonWithFields.cs new file mode 100644 index 00000000..2cd9c128 --- /dev/null +++ b/tests/ObjectPrintingTests/PersonWithFields.cs @@ -0,0 +1,9 @@ +namespace ObjectPrintingTests; + +public class PersonWithFields +{ + public Guid Id; + public string Name; + public double Height; + public int Age; +} \ No newline at end of file From a734a24fde7f03a160644634255163d3e669ae5d Mon Sep 17 00:00:00 2001 From: S4MPAI Date: Sun, 15 Dec 2024 00:33:21 +0500 Subject: [PATCH 07/12] change tests to using ApprovalTests library --- ...ing_ShouldSerializeDictionary.approved.txt | 4 ++ ...tToString_ShouldSerializeList.approved.txt | 5 ++ ...alizePerson_WhenExcludeFields.approved.txt | 4 ++ ...izePerson_WhenExcludeProperty.approved.txt | 4 ++ ...rializePerson_WhenExcludeType.approved.txt | 4 ++ ...Person_WhenHaveCycleReference.approved.txt | 6 ++ ...erializePerson_WhenTrimString.approved.txt | 5 ++ ...rson_WhenUseCustomCultureInfo.approved.txt | 6 ++ ...eCustomSerializationForMember.approved.txt | 5 ++ ...UseCustomSerializationForType.approved.txt | 6 ++ ...SerializePerson_WhenUseFields.approved.txt | 5 ++ ...alizePerson_WhenUseProperties.approved.txt | 5 ++ .../ObjectPrintingTests/ObjectPrinterTests.cs | 67 ++++++------------- .../ObjectPrintingTests.csproj | 1 + 14 files changed, 82 insertions(+), 45 deletions(-) create mode 100644 tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializeDictionary.approved.txt create mode 100644 tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializeList.approved.txt create mode 100644 tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeFields.approved.txt create mode 100644 tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeProperty.approved.txt create mode 100644 tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeType.approved.txt create mode 100644 tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenHaveCycleReference.approved.txt create mode 100644 tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenTrimString.approved.txt create mode 100644 tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomCultureInfo.approved.txt create mode 100644 tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForMember.approved.txt create mode 100644 tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForType.approved.txt create mode 100644 tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseFields.approved.txt create mode 100644 tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseProperties.approved.txt diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializeDictionary.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializeDictionary.approved.txt new file mode 100644 index 00000000..50c71672 --- /dev/null +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializeDictionary.approved.txt @@ -0,0 +1,4 @@ +Dictionary + 1 : test1 + 2 : test2 + 3 : test3 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializeList.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializeList.approved.txt new file mode 100644 index 00000000..14f4d40a --- /dev/null +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializeList.approved.txt @@ -0,0 +1,5 @@ +Collection + 1 + 2 + 3 + 4 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeFields.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeFields.approved.txt new file mode 100644 index 00000000..b6705877 --- /dev/null +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeFields.approved.txt @@ -0,0 +1,4 @@ +PersonWithFields + Name = John + Height = 175 + Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeProperty.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeProperty.approved.txt new file mode 100644 index 00000000..96626bb5 --- /dev/null +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeProperty.approved.txt @@ -0,0 +1,4 @@ +Person + Name = John + Height = 175 + Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeType.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeType.approved.txt new file mode 100644 index 00000000..9e59bf51 --- /dev/null +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeType.approved.txt @@ -0,0 +1,4 @@ +PersonWithWeight + Id = Guid + Name = John + Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenHaveCycleReference.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenHaveCycleReference.approved.txt new file mode 100644 index 00000000..6a8d6b85 --- /dev/null +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenHaveCycleReference.approved.txt @@ -0,0 +1,6 @@ +PersonWithParent + Id = Guid + Name = John + Height = 175 + Age = 25 + Parent = cycled PersonWithParent in level 0 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenTrimString.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenTrimString.approved.txt new file mode 100644 index 00000000..8e5a662f --- /dev/null +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenTrimString.approved.txt @@ -0,0 +1,5 @@ +Person + Id = Guid + Name = John + Height = 175 + Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomCultureInfo.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomCultureInfo.approved.txt new file mode 100644 index 00000000..6cb982f0 --- /dev/null +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomCultureInfo.approved.txt @@ -0,0 +1,6 @@ +PersonWithWeight + Id = Guid + Name = John + Height = 175.5 + Weight = 70.5 + Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForMember.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForMember.approved.txt new file mode 100644 index 00000000..0584d4b1 --- /dev/null +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForMember.approved.txt @@ -0,0 +1,5 @@ +Person + Id = Guid + Name = John + Height = 176 + Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForType.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForType.approved.txt new file mode 100644 index 00000000..10585393 --- /dev/null +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForType.approved.txt @@ -0,0 +1,6 @@ +PersonWithWeight + Id = Guid + Name = John + Height = 175,00 + Weight = 70,00 + Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseFields.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseFields.approved.txt new file mode 100644 index 00000000..3cc8d50e --- /dev/null +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseFields.approved.txt @@ -0,0 +1,5 @@ +PersonWithFields + Id = Guid + Name = John + Height = 175 + Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseProperties.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseProperties.approved.txt new file mode 100644 index 00000000..8e5a662f --- /dev/null +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseProperties.approved.txt @@ -0,0 +1,5 @@ +Person + Id = Guid + Name = John + Height = 175 + Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterTests.cs b/tests/ObjectPrintingTests/ObjectPrinterTests.cs index fe3e0524..f897521a 100644 --- a/tests/ObjectPrintingTests/ObjectPrinterTests.cs +++ b/tests/ObjectPrintingTests/ObjectPrinterTests.cs @@ -1,10 +1,14 @@ using System.Globalization; +using ApprovalTests; +using ApprovalTests.Namers; +using ApprovalTests.Reporters; using FluentAssertions; using ObjectPrinting; namespace ObjectPrintingTests; -[TestFixture] +[UseReporter(typeof(DiffReporter))] +[UseApprovalSubdirectory("ObjectPrinterResults")] public class ObjectPrinterTests { [Test] @@ -13,9 +17,8 @@ public void PrintToString_ShouldSerializePerson_WhenUseProperties() var person = new Person { Name = "John", Age = 25, Height = 175}; var actualResult = ObjectPrinter.For().PrintToString(person); - var expectedResult = "Person\r\n\tId = Guid\r\n\tName = John\r\n\tHeight = 175\r\n\tAge = 25\r\n"; - actualResult.Should().BeEquivalentTo(expectedResult); + Approvals.Verify(actualResult); } [Test] @@ -24,9 +27,8 @@ public void PrintToString_ShouldSerializePerson_WhenUseFields() var person = new PersonWithFields { Name = "John", Age = 25, Height = 175}; var actualResult = ObjectPrinter.For().PrintToString(person); - var expectedResult = "PersonWithFields\r\n\tId = Guid\r\n\tName = John\r\n\tHeight = 175\r\n\tAge = 25\r\n"; - actualResult.Should().BeEquivalentTo(expectedResult); + Approvals.Verify(actualResult); } [Test] @@ -35,9 +37,8 @@ public void PrintToString_ShouldSerializePerson_WhenExcludeType() var personWithWeight = new PersonWithWeight { Name = "John", Age = 25, Height = 175, Weight = 70 }; var actualResult = ObjectPrinter.For().Excluding().PrintToString(personWithWeight); - var expectedResult = "PersonWithWeight\r\n\tId = Guid\r\n\tName = John\r\n\tAge = 25\r\n"; - actualResult.Should().BeEquivalentTo(expectedResult); + Approvals.Verify(actualResult); } [Test] @@ -46,9 +47,8 @@ public void PrintToString_ShouldSerializePerson_WhenExcludeProperty() var person = new Person { Name = "John", Age = 25, Height = 175 }; var actualResult = ObjectPrinter.For().Excluding(p => p.Id).PrintToString(person); - var expectedResult = "Person\r\n\tName = John\r\n\tHeight = 175\r\n\tAge = 25\r\n"; - actualResult.Should().BeEquivalentTo(expectedResult); + Approvals.Verify(actualResult); } [Test] @@ -57,9 +57,8 @@ public void PrintToString_ShouldSerializePerson_WhenExcludeFields() var person = new PersonWithFields { Name = "John", Age = 25, Height = 175 }; var actualResult = ObjectPrinter.For().Excluding(p => p.Id).PrintToString(person); - var expectedResult = "PersonWithFields\r\n\tName = John\r\n\tHeight = 175\r\n\tAge = 25\r\n"; - actualResult.Should().BeEquivalentTo(expectedResult); + Approvals.Verify(actualResult); } [Test] @@ -71,14 +70,8 @@ public void PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForTyp .For() .For().Using(x => $"{x:F2}") .PrintToString(personWithWeight); - var expectedResult = "PersonWithWeight\r\n" + - "\tId = Guid\r\n" + - "\tName = John\r\n" + - "\tHeight = 175,00\r\n" + - "\tWeight = 70,00\r\n" + - "\tAge = 25\r\n"; - - actualResult.Should().BeEquivalentTo(expectedResult); + + Approvals.Verify(actualResult); } [Test] @@ -90,14 +83,8 @@ public void PrintToString_ShouldSerializePerson_WhenUseCustomCultureInfo() .For() .For().Using(CultureInfo.InvariantCulture) .PrintToString(personWithWeight); - var expectedResult = "PersonWithWeight\r\n" + - "\tId = Guid\r\n" + - "\tName = John\r\n" + - "\tHeight = 175.5\r\n" + - "\tWeight = 70.5\r\n" + - "\tAge = 25\r\n"; - - actualResult.Should().BeEquivalentTo(expectedResult); + + Approvals.Verify(actualResult); } [Test] @@ -109,9 +96,8 @@ public void PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForMem .For() .For(p => p.Height).Using(h => ((int)Math.Round(h)).ToString()) .PrintToString(person); - var expectedResult = "Person\r\n\tId = Guid\r\n\tName = John\r\n\tHeight = 176\r\n\tAge = 25\r\n"; - actualResult.Should().BeEquivalentTo(expectedResult); + Approvals.Verify(actualResult); } [Test] @@ -123,9 +109,8 @@ public void PrintToString_ShouldSerializePerson_WhenTrimString() .For() .For(p => p.Name).MaxLength(4) .PrintToString(person); - var expectedResult = "Person\r\n\tId = Guid\r\n\tName = John\r\n\tHeight = 175\r\n\tAge = 25\r\n"; - actualResult.Should().BeEquivalentTo(expectedResult); + Approvals.Verify(actualResult); } [Test] @@ -137,14 +122,8 @@ public void PrintToString_ShouldSerializePerson_WhenHaveCycleReference() var actualResult = ObjectPrinter .For() .PrintToString(personWithParent); - var expectedResult = "PersonWithParent\r\n" + - "\tId = Guid\r\n" + - "\tName = John\r\n" + - "\tHeight = 175\r\n" + - "\tAge = 25\r\n" + - "\tParent = cycled PersonWithParent in level 0\r\n"; - - actualResult.Should().BeEquivalentTo(expectedResult); + + Approvals.Verify(actualResult); } [Test] @@ -155,9 +134,8 @@ public void PrintToString_ShouldSerializeList() var actualResult = ObjectPrinter .For() .PrintToString(numbers); - var expectedResult = "Collection\r\n\t1\r\n\t2\r\n\t3\r\n\t4\r\n"; - - actualResult.Should().BeEquivalentTo(expectedResult); + + Approvals.Verify(actualResult); } [Test] @@ -173,8 +151,7 @@ public void PrintToString_ShouldSerializeDictionary() var actualResult = ObjectPrinter .For>() .PrintToString(dictionary); - var expectedResult = "Dictionary\r\n\t1 : test1\r\n\t2 : test2\r\n\t3 : test3\r\n"; - - actualResult.Should().BeEquivalentTo(expectedResult); + + Approvals.Verify(actualResult); } } \ No newline at end of file diff --git a/tests/ObjectPrintingTests/ObjectPrintingTests.csproj b/tests/ObjectPrintingTests/ObjectPrintingTests.csproj index 2d570d73..f92a3eaa 100644 --- a/tests/ObjectPrintingTests/ObjectPrintingTests.csproj +++ b/tests/ObjectPrintingTests/ObjectPrintingTests.csproj @@ -10,6 +10,7 @@ + From 84286e20afb685dea999003510adbfb21fd34dd4 Mon Sep 17 00:00:00 2001 From: S4MPAI Date: Sun, 15 Dec 2024 14:06:59 +0500 Subject: [PATCH 08/12] refactor printing configs of members --- ObjectPrinting/MemberPrintingConfig.cs | 21 +++++++++++++++ .../MemberPrintingConfigExtensions.cs | 22 +++++++++++++++ ObjectPrinting/PrintingConfig.cs | 6 ++--- ObjectPrinting/PropertyPrintingConfig.cs | 21 --------------- .../PropertyPrintingConfigExtensions.cs | 27 ------------------- ObjectPrinting/TypePrintingConfig.cs | 8 +++--- ObjectPrinting/TypePrintingExtensions.cs | 11 +++----- 7 files changed, 53 insertions(+), 63 deletions(-) create mode 100644 ObjectPrinting/MemberPrintingConfig.cs create mode 100644 ObjectPrinting/MemberPrintingConfigExtensions.cs delete mode 100644 ObjectPrinting/PropertyPrintingConfig.cs delete mode 100644 ObjectPrinting/PropertyPrintingConfigExtensions.cs diff --git a/ObjectPrinting/MemberPrintingConfig.cs b/ObjectPrinting/MemberPrintingConfig.cs new file mode 100644 index 00000000..a1ecf073 --- /dev/null +++ b/ObjectPrinting/MemberPrintingConfig.cs @@ -0,0 +1,21 @@ +using System; +using System.Linq; +using System.Reflection; +using ObjectPrinting.Serializers; + +namespace ObjectPrinting; + +public class MemberPrintingConfig(PrintingConfig headConfig, MemberInfo memberInfo) +{ + internal PrintingConfig HeadConfig => headConfig; + internal MemberInfo MemberInfo => memberInfo; + internal readonly MembersSerializerByMember Serializer = + headConfig.MembersSerializers.OfType().First(); + + public PrintingConfig Using(Func printing) + { + Serializer.SerializerRules[MemberInfo] = p => printing((TProperty)p); + + return HeadConfig; + } +} \ No newline at end of file diff --git a/ObjectPrinting/MemberPrintingConfigExtensions.cs b/ObjectPrinting/MemberPrintingConfigExtensions.cs new file mode 100644 index 00000000..0526098b --- /dev/null +++ b/ObjectPrinting/MemberPrintingConfigExtensions.cs @@ -0,0 +1,22 @@ +using System; + +namespace ObjectPrinting; + +public static class MemberPrintingConfigExtensions +{ + public static PrintingConfig MaxLength( + this MemberPrintingConfig memberPrintingConfig, + int maxLength) + { + var serializerRules = memberPrintingConfig.Serializer.SerializerRules; + serializerRules[memberPrintingConfig.MemberInfo] = x => TrimString(x, maxLength); + + return memberPrintingConfig.HeadConfig; + } + + private static string TrimString(object value, int maxLength) + { + var propertyString = (value as string)!; + return propertyString[..Math.Min(propertyString.Length, maxLength)]; + } +} \ No newline at end of file diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 267755b5..45e8120a 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -43,7 +43,7 @@ public PrintingConfig Excluding(Expression For() => new(this); - public PropertyPrintingConfig For(Expression> memberSelector) => + public MemberPrintingConfig For(Expression> memberSelector) => new(this, GetMember(memberSelector)); public string PrintToString(TOwner obj) => @@ -130,10 +130,10 @@ private string PrintClassProperties(object obj, int nestingLevel, Dictionary(Expression> memberSelector) + private static MemberInfo GetMember(Expression> memberSelector) { if (memberSelector.Body is not MemberExpression memberExpression) - throw new ArgumentException("Expression refers to a method, not a property."); + throw new ArgumentException("Expression refers to a method, not a member."); return memberExpression.Member; } diff --git a/ObjectPrinting/PropertyPrintingConfig.cs b/ObjectPrinting/PropertyPrintingConfig.cs deleted file mode 100644 index c16722e8..00000000 --- a/ObjectPrinting/PropertyPrintingConfig.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using ObjectPrinting.Serializers; - -namespace ObjectPrinting; - -public class PropertyPrintingConfig(PrintingConfig headConfig, MemberInfo memberInfo) -{ - public PrintingConfig HeadConfig => headConfig; - public MemberInfo PropertyInfo => memberInfo; - - public PrintingConfig Using(Func printing) - { - ((MembersSerializerByMember)HeadConfig.MembersSerializers - .First(x => x is MembersSerializerByMember)) - .SerializerRules[PropertyInfo] = p => printing((TProperty)p); - - return HeadConfig; - } -} \ No newline at end of file diff --git a/ObjectPrinting/PropertyPrintingConfigExtensions.cs b/ObjectPrinting/PropertyPrintingConfigExtensions.cs deleted file mode 100644 index 0f0a4611..00000000 --- a/ObjectPrinting/PropertyPrintingConfigExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Linq; -using ObjectPrinting.Serializers; - -namespace ObjectPrinting; - -public static class PropertyPrintingConfigExtensions -{ - public static PrintingConfig MaxLength( - this PropertyPrintingConfig propertyPrintingConfig, - int maxLength) - { - var headConfig = propertyPrintingConfig.HeadConfig; - - ((MembersSerializerByMember)headConfig.MembersSerializers - .First(x => x is MembersSerializerByMember)) - .SerializerRules[propertyPrintingConfig.PropertyInfo] = x => TrimString(x, maxLength); - - return headConfig; - } - - private static string TrimString(object value, int maxLength) - { - var propertyString = (value as string)!; - return propertyString[..Math.Min(propertyString.Length, maxLength)]; - } -} \ No newline at end of file diff --git a/ObjectPrinting/TypePrintingConfig.cs b/ObjectPrinting/TypePrintingConfig.cs index 74344951..59577dfd 100644 --- a/ObjectPrinting/TypePrintingConfig.cs +++ b/ObjectPrinting/TypePrintingConfig.cs @@ -6,13 +6,13 @@ namespace ObjectPrinting; public class TypePrintingConfig(PrintingConfig headConfig) { - public PrintingConfig HeadConfig { get; } = headConfig; + internal PrintingConfig HeadConfig { get; } = headConfig; + internal readonly MembersSerializerByType Serializer = + headConfig.MembersSerializers.OfType().First(); public PrintingConfig Using(Func printing) { - ((MembersSerializerByType)HeadConfig.MembersSerializers - .First(x => x is MembersSerializerByType)) - .SerializerRules[typeof(TPropertyType)] = p => printing((TPropertyType)p); + Serializer.SerializerRules[typeof(TPropertyType)] = p => printing((TPropertyType)p); return HeadConfig; } diff --git a/ObjectPrinting/TypePrintingExtensions.cs b/ObjectPrinting/TypePrintingExtensions.cs index 42c946f0..a6d64a1c 100644 --- a/ObjectPrinting/TypePrintingExtensions.cs +++ b/ObjectPrinting/TypePrintingExtensions.cs @@ -1,7 +1,5 @@ using System; using System.Globalization; -using System.Linq; -using ObjectPrinting.Serializers; namespace ObjectPrinting; @@ -11,12 +9,9 @@ public static PrintingConfig Using( this TypePrintingConfig config, CultureInfo cultureInfo) where T : IFormattable { - var headConfig = config.HeadConfig; + var serializerRules = config.Serializer.SerializerRules; + serializerRules[typeof(T)] = x => string.Format(cultureInfo, "{0}", x); - ((MembersSerializerByType)headConfig.MembersSerializers - .First(x => x is MembersSerializerByType)) - .SerializerRules[typeof(T)] = x => string.Format(cultureInfo, "{0}", x); - - return headConfig; + return config.HeadConfig; } } \ No newline at end of file From bc5b75c33efd723ee83252dab48ca928f55de2db Mon Sep 17 00:00:00 2001 From: S4MPAI Date: Sun, 15 Dec 2024 14:18:15 +0500 Subject: [PATCH 09/12] rename protected TrySerialize method --- ObjectPrinting/Serializers/BaseMembersSerializer.cs | 4 ++-- ObjectPrinting/Serializers/MembersSerializerByMember.cs | 2 +- ObjectPrinting/Serializers/MembersSerializerByType.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ObjectPrinting/Serializers/BaseMembersSerializer.cs b/ObjectPrinting/Serializers/BaseMembersSerializer.cs index 3fd8ec29..d8dd6ff0 100644 --- a/ObjectPrinting/Serializers/BaseMembersSerializer.cs +++ b/ObjectPrinting/Serializers/BaseMembersSerializer.cs @@ -10,10 +10,10 @@ public bool TrySerialize(object obj, MemberInfo memberInfo, out string result) { result = null!; return MemberHelper.TryGetTypeAndValueOfMember(obj, memberInfo, out var memberData) && - TrySerializeProtected(memberData!.Value.memberValue, memberData.Value.memberType, memberInfo, out result); + TrySerializeCore(memberData!.Value.memberValue, memberData.Value.memberType, memberInfo, out result); } - protected abstract bool TrySerializeProtected( + protected abstract bool TrySerializeCore( object memberValue, Type memberType, MemberInfo memberInfo, diff --git a/ObjectPrinting/Serializers/MembersSerializerByMember.cs b/ObjectPrinting/Serializers/MembersSerializerByMember.cs index efb2033b..f3e87605 100644 --- a/ObjectPrinting/Serializers/MembersSerializerByMember.cs +++ b/ObjectPrinting/Serializers/MembersSerializerByMember.cs @@ -8,7 +8,7 @@ public class MembersSerializerByMember : BaseMembersSerializer { public Dictionary> SerializerRules { get; } = new(); - protected override bool TrySerializeProtected( + protected override bool TrySerializeCore( object memberValue, Type memberType, MemberInfo memberInfo, diff --git a/ObjectPrinting/Serializers/MembersSerializerByType.cs b/ObjectPrinting/Serializers/MembersSerializerByType.cs index f134cbb9..66b1b413 100644 --- a/ObjectPrinting/Serializers/MembersSerializerByType.cs +++ b/ObjectPrinting/Serializers/MembersSerializerByType.cs @@ -8,7 +8,7 @@ public class MembersSerializerByType : BaseMembersSerializer { public Dictionary> SerializerRules { get; } = new(); - protected override bool TrySerializeProtected( + protected override bool TrySerializeCore( object memberValue, Type memberType, MemberInfo memberInfo, From 0c12bd1ebdce9a268508de61146202e8e443af32 Mon Sep 17 00:00:00 2001 From: S4MPAI Date: Sun, 15 Dec 2024 14:43:11 +0500 Subject: [PATCH 10/12] fix guid serialization --- ObjectPrinting/PrintingConfig.cs | 1 + ...tToString_ShouldSerializePerson_WhenExcludeType.approved.txt | 2 +- ...ng_ShouldSerializePerson_WhenHaveCycleReference.approved.txt | 2 +- ...ntToString_ShouldSerializePerson_WhenTrimString.approved.txt | 2 +- ..._ShouldSerializePerson_WhenUseCustomCultureInfo.approved.txt | 2 +- ...alizePerson_WhenUseCustomSerializationForMember.approved.txt | 2 +- ...intToString_ShouldSerializePerson_WhenUseFields.approved.txt | 2 +- ...oString_ShouldSerializePerson_WhenUseProperties.approved.txt | 2 +- 8 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 45e8120a..98c97349 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -20,6 +20,7 @@ public class PrintingConfig private readonly HashSet primitiveTypes = [ + typeof(Guid), typeof(string), typeof(DateTime), typeof(TimeSpan) diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeType.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeType.approved.txt index 9e59bf51..b20e7066 100644 --- a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeType.approved.txt +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenExcludeType.approved.txt @@ -1,4 +1,4 @@ PersonWithWeight - Id = Guid + Id = 00000000-0000-0000-0000-000000000000 Name = John Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenHaveCycleReference.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenHaveCycleReference.approved.txt index 6a8d6b85..e7f7f429 100644 --- a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenHaveCycleReference.approved.txt +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenHaveCycleReference.approved.txt @@ -1,5 +1,5 @@ PersonWithParent - Id = Guid + Id = 00000000-0000-0000-0000-000000000000 Name = John Height = 175 Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenTrimString.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenTrimString.approved.txt index 8e5a662f..a88e0138 100644 --- a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenTrimString.approved.txt +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenTrimString.approved.txt @@ -1,5 +1,5 @@ Person - Id = Guid + Id = 00000000-0000-0000-0000-000000000000 Name = John Height = 175 Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomCultureInfo.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomCultureInfo.approved.txt index 6cb982f0..38c337a1 100644 --- a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomCultureInfo.approved.txt +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomCultureInfo.approved.txt @@ -1,5 +1,5 @@ PersonWithWeight - Id = Guid + Id = 00000000-0000-0000-0000-000000000000 Name = John Height = 175.5 Weight = 70.5 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForMember.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForMember.approved.txt index 0584d4b1..88407ac0 100644 --- a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForMember.approved.txt +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForMember.approved.txt @@ -1,5 +1,5 @@ Person - Id = Guid + Id = 00000000-0000-0000-0000-000000000000 Name = John Height = 176 Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseFields.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseFields.approved.txt index 3cc8d50e..2f575529 100644 --- a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseFields.approved.txt +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseFields.approved.txt @@ -1,5 +1,5 @@ PersonWithFields - Id = Guid + Id = 00000000-0000-0000-0000-000000000000 Name = John Height = 175 Age = 25 diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseProperties.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseProperties.approved.txt index 8e5a662f..a88e0138 100644 --- a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseProperties.approved.txt +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseProperties.approved.txt @@ -1,5 +1,5 @@ Person - Id = Guid + Id = 00000000-0000-0000-0000-000000000000 Name = John Height = 175 Age = 25 From 8297e5fd323c7cc81f1969453d08d4b2e8c8c256 Mon Sep 17 00:00:00 2001 From: S4MPAI Date: Sun, 15 Dec 2024 14:44:16 +0500 Subject: [PATCH 11/12] small fix --- ...rializePerson_WhenUseCustomSerializationForType.approved.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForType.approved.txt b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForType.approved.txt index 10585393..c3505009 100644 --- a/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForType.approved.txt +++ b/tests/ObjectPrintingTests/ObjectPrinterResults/ObjectPrinterTests.PrintToString_ShouldSerializePerson_WhenUseCustomSerializationForType.approved.txt @@ -1,5 +1,5 @@ PersonWithWeight - Id = Guid + Id = 00000000-0000-0000-0000-000000000000 Name = John Height = 175,00 Weight = 70,00 From c10123f332d9ddaefa50540e3b83114767268939 Mon Sep 17 00:00:00 2001 From: S4MPAI Date: Sun, 15 Dec 2024 15:43:46 +0500 Subject: [PATCH 12/12] refactor getting members value and type --- ObjectPrinting/Helpers/MemberHelper.cs | 20 ------------- ObjectPrinting/PrintingConfig.cs | 28 +++++++++---------- .../Serializers/BaseMembersSerializer.cs | 21 -------------- .../Serializers/IMembersSerializer.cs | 3 +- .../Serializers/MembersSerializerByMember.cs | 4 +-- .../Serializers/MembersSerializerByType.cs | 4 +-- 6 files changed, 20 insertions(+), 60 deletions(-) delete mode 100644 ObjectPrinting/Serializers/BaseMembersSerializer.cs diff --git a/ObjectPrinting/Helpers/MemberHelper.cs b/ObjectPrinting/Helpers/MemberHelper.cs index 2ec5ce54..075585e8 100644 --- a/ObjectPrinting/Helpers/MemberHelper.cs +++ b/ObjectPrinting/Helpers/MemberHelper.cs @@ -5,26 +5,6 @@ namespace ObjectPrinting.Helpers; public static class MemberHelper { - public static bool TryGetMemberValue(object declaringObj, MemberInfo memberInfo, out object value) - { - value = null!; - if (!TryGetTypeAndValueOfMember(declaringObj, memberInfo, out var memberData)) - return false; - - value = memberData!.Value.memberValue; - return true; - } - - public static bool TryGetMemberType(object declaringObj, MemberInfo memberInfo, out Type type) - { - type = null!; - if (!TryGetTypeAndValueOfMember(declaringObj, memberInfo, out var memberData)) - return false; - - type = memberData!.Value.memberType; - return true; - } - public static bool TryGetTypeAndValueOfMember( object declaringObj, MemberInfo memberInfo, diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 98c97349..4615d641 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -26,7 +26,7 @@ public class PrintingConfig typeof(TimeSpan) ]; private readonly HashSet excludingTypes = []; - private readonly HashSet excludingProperties = []; + private readonly HashSet excludingMembers = []; public PrintingConfig Excluding() { @@ -37,7 +37,7 @@ public PrintingConfig Excluding() public PrintingConfig Excluding(Expression> memberSelector) { - excludingProperties.Add(GetMember(memberSelector)); + excludingMembers.Add(GetMember(memberSelector)); return this; } @@ -59,7 +59,7 @@ private string PrintToString(object obj, int nestingLevel, Dictionary m.MemberType is MemberTypes.Property or MemberTypes.Field).ToList(); - foreach (var memberInfo in neededMembers) + foreach (var memberInfo in type.GetMembers(BindingFlags.Instance | BindingFlags.Public)) { - MemberHelper.TryGetMemberType(obj, memberInfo, out var memberType); - if (excludingProperties.Contains(memberInfo) || excludingTypes.Contains(memberType)) + if (!MemberHelper.TryGetTypeAndValueOfMember(obj, memberInfo, out var memberData)) + continue; + + var (memberValue, memberType) = memberData!.Value; + if (excludingMembers.Contains(memberInfo) || excludingTypes.Contains(memberType)) continue; sb.Append(identation + memberInfo.Name + " = " + - PrintMember(obj, memberInfo, nextNestingLevel, parsedObjects)); + PrintMember(memberValue, memberType, memberInfo, nextNestingLevel, parsedObjects)); } return sb.ToString(); @@ -140,7 +140,8 @@ private static MemberInfo GetMember(Expression parsedObjects) @@ -148,12 +149,11 @@ private string PrintMember( string? result = null; foreach (var serializer in MembersSerializers) - if (serializer.TrySerialize(obj, memberInfo, out result)) + if (serializer.TrySerialize(memberValue, memberType, memberInfo, out result)) break; - MemberHelper.TryGetMemberValue(obj, memberInfo, out var propertyValue); return result == null - ? PrintToString(propertyValue, nextNestingLevel, parsedObjects) + ? PrintToString(memberValue, nextNestingLevel, parsedObjects) : result + Environment.NewLine; } } diff --git a/ObjectPrinting/Serializers/BaseMembersSerializer.cs b/ObjectPrinting/Serializers/BaseMembersSerializer.cs deleted file mode 100644 index d8dd6ff0..00000000 --- a/ObjectPrinting/Serializers/BaseMembersSerializer.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Reflection; -using ObjectPrinting.Helpers; - -namespace ObjectPrinting.Serializers; - -public abstract class BaseMembersSerializer : IMembersSerializer -{ - public bool TrySerialize(object obj, MemberInfo memberInfo, out string result) - { - result = null!; - return MemberHelper.TryGetTypeAndValueOfMember(obj, memberInfo, out var memberData) && - TrySerializeCore(memberData!.Value.memberValue, memberData.Value.memberType, memberInfo, out result); - } - - protected abstract bool TrySerializeCore( - object memberValue, - Type memberType, - MemberInfo memberInfo, - out string serializedMemberInfo); -} \ No newline at end of file diff --git a/ObjectPrinting/Serializers/IMembersSerializer.cs b/ObjectPrinting/Serializers/IMembersSerializer.cs index c8a89f9c..696231d3 100644 --- a/ObjectPrinting/Serializers/IMembersSerializer.cs +++ b/ObjectPrinting/Serializers/IMembersSerializer.cs @@ -1,8 +1,9 @@ +using System; using System.Reflection; namespace ObjectPrinting.Serializers; public interface IMembersSerializer { - public bool TrySerialize(object obj, MemberInfo memberInfo, out string result); + public bool TrySerialize(object memberValue, Type memberType, MemberInfo memberInfo, out string result); } \ No newline at end of file diff --git a/ObjectPrinting/Serializers/MembersSerializerByMember.cs b/ObjectPrinting/Serializers/MembersSerializerByMember.cs index f3e87605..7bfb3397 100644 --- a/ObjectPrinting/Serializers/MembersSerializerByMember.cs +++ b/ObjectPrinting/Serializers/MembersSerializerByMember.cs @@ -4,11 +4,11 @@ namespace ObjectPrinting.Serializers; -public class MembersSerializerByMember : BaseMembersSerializer +public class MembersSerializerByMember : IMembersSerializer { public Dictionary> SerializerRules { get; } = new(); - protected override bool TrySerializeCore( + public bool TrySerialize( object memberValue, Type memberType, MemberInfo memberInfo, diff --git a/ObjectPrinting/Serializers/MembersSerializerByType.cs b/ObjectPrinting/Serializers/MembersSerializerByType.cs index 66b1b413..f8dc294e 100644 --- a/ObjectPrinting/Serializers/MembersSerializerByType.cs +++ b/ObjectPrinting/Serializers/MembersSerializerByType.cs @@ -4,11 +4,11 @@ namespace ObjectPrinting.Serializers; -public class MembersSerializerByType : BaseMembersSerializer +public class MembersSerializerByType : IMembersSerializer { public Dictionary> SerializerRules { get; } = new(); - protected override bool TrySerializeCore( + public bool TrySerialize( object memberValue, Type memberType, MemberInfo memberInfo,