From 362434bed54bd82f5b5f4003ed44b2570071468f Mon Sep 17 00:00:00 2001 From: Leonid Date: Wed, 11 Dec 2024 00:42:29 +0500 Subject: [PATCH 1/9] Add structure fluent api interface --- .../Extensions/NumericCultureExtension.cs | 16 +++++ .../StringPrintingConfigurationExtension.cs | 13 ++++ ObjectPrinting/PrintingConfig.cs | 68 +++++++++++++++++++ ObjectPrinting/PrintingConfiguration.cs | 33 +++++++++ fluent-api.sln.DotSettings | 3 + 5 files changed, 133 insertions(+) create mode 100644 ObjectPrinting/Extensions/NumericCultureExtension.cs create mode 100644 ObjectPrinting/Extensions/StringPrintingConfigurationExtension.cs create mode 100644 ObjectPrinting/PrintingConfiguration.cs diff --git a/ObjectPrinting/Extensions/NumericCultureExtension.cs b/ObjectPrinting/Extensions/NumericCultureExtension.cs new file mode 100644 index 00000000..ced6c4aa --- /dev/null +++ b/ObjectPrinting/Extensions/NumericCultureExtension.cs @@ -0,0 +1,16 @@ +using System; +using System.Globalization; + +namespace ObjectPrinting.Extensions; + +public static class NumericCultureExtension +{ + public static PrintingConfig UseCulture( + this PrintingConfiguration propertyStringConfiguration, + CultureInfo culture) where TNumericType : IFormattable + { + propertyStringConfiguration.ParentConfig.AddNumericCulture(culture); + + return propertyStringConfiguration.ParentConfig; + } +} \ No newline at end of file diff --git a/ObjectPrinting/Extensions/StringPrintingConfigurationExtension.cs b/ObjectPrinting/Extensions/StringPrintingConfigurationExtension.cs new file mode 100644 index 00000000..17dbe342 --- /dev/null +++ b/ObjectPrinting/Extensions/StringPrintingConfigurationExtension.cs @@ -0,0 +1,13 @@ +namespace ObjectPrinting.Extensions; + +public static class StringPrintingConfigurationExtension +{ + public static PrintingConfig TrimmedToLength( + this PrintingConfiguration propertyStringConfiguration, int length) + { + propertyStringConfiguration.ParentConfig + .AddStringPropertyTrim(propertyStringConfiguration.PropertyMemberInfo.Name, length); + + return propertyStringConfiguration.ParentConfig; + } +} \ No newline at end of file diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index a9e08211..f3c4e738 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -1,16 +1,61 @@ +using ObjectPrinting.Solved; using System; +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 { + private readonly HashSet excludedTypes = new(); + private readonly HashSet excludedProperties = new(); + private readonly Dictionary typeSerializers = new(); + private readonly Dictionary propertySerializers = new(); + private readonly Dictionary typeCultures = new(); + private readonly Dictionary propertyTrim = new(); + + // : + + // 1. + public PrintingConfig ExcludePropertiesWithType() + { + excludedTypes.Add(typeof(TPropType)); + return this; + } + + // 2. + public PrintingConfiguration Printing( + Expression> propertySelector) + { + var memberInfo = GetPropertyName(propertySelector); + return new PrintingConfiguration(this, memberInfo); + } + + public PrintingConfiguration Printing() + { + return new PrintingConfiguration(this, null); + } + + // 6. + public PrintingConfig Exclude(Expression> propertySelector) + { + var propertyName = GetPropertyName(propertySelector); + excludedProperties.Add(propertyName); + return this; + } + + // + public string PrintToString(TOwner obj) { return PrintToString(obj, 0); } + private string PrintToString(object obj, int nestingLevel) { //TODO apply configurations @@ -37,5 +82,28 @@ private string PrintToString(object obj, int nestingLevel) } return sb.ToString(); } + + private MemberInfo GetPropertyName(Expression> propertySelector) + { + if (propertySelector.Body is MemberExpression memberExpression) + return memberExpression.Member; + + if (propertySelector.Body is UnaryExpression unaryExpression && unaryExpression.Operand is MemberExpression operand) + return operand.Member; + + throw new ArgumentException("Invalid property selector expression"); + } + + internal void AddPropertySerializer(string propertyName, Func serializer) => + propertySerializers[propertyName] = serializer; + + internal void AddTypeSerializer(Func serializer) => + typeSerializers[typeof(TPropType)] = serializer; + + internal void AddStringPropertyTrim(string propertyName, int maxLength) => + propertyTrim[propertyName] = maxLength; + + internal void AddNumericCulture(CultureInfo culture) => + typeCultures[typeof(TNumericCulture)] = culture; } } \ No newline at end of file diff --git a/ObjectPrinting/PrintingConfiguration.cs b/ObjectPrinting/PrintingConfiguration.cs new file mode 100644 index 00000000..aa5bf83e --- /dev/null +++ b/ObjectPrinting/PrintingConfiguration.cs @@ -0,0 +1,33 @@ +using System; +using System.Reflection; + +namespace ObjectPrinting; + +public class PrintingConfiguration +{ + private readonly PrintingConfig parentConfig; + private readonly MemberInfo? propertyMemberInfo; + + internal PrintingConfig ParentConfig => parentConfig; + internal MemberInfo? PropertyMemberInfo => propertyMemberInfo; + + public PrintingConfiguration(PrintingConfig parentConfig, MemberInfo? propertyMemberInfo) + { + this.parentConfig = parentConfig; + this.propertyMemberInfo = propertyMemberInfo; + } + + public PrintingConfig Using(Func printingMethod) + { + if (propertyMemberInfo == null) + { + parentConfig.AddTypeSerializer(printingMethod); + } + else + { + parentConfig.AddPropertySerializer(propertyMemberInfo.Name, printingMethod); + } + + return parentConfig; + } +} \ 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 8280b75fc1c2b236a9070076d0b77cabf4e11ce4 Mon Sep 17 00:00:00 2001 From: Leonid Date: Wed, 11 Dec 2024 23:04:12 +0500 Subject: [PATCH 2/9] complete full logic --- .../Extensions/ObjectPrinterExtension.cs | 12 ++ ObjectPrinting/PrintingConfig.cs | 104 ++++++++++++++---- .../Tests/ObjectPrinterAcceptanceTests.cs | 20 +++- .../Solved => Solved}/ObjectExtensions.cs | 0 .../Solved => Solved}/ObjectPrinter.cs | 0 .../Solved => Solved}/PrintingConfig.cs | 0 .../PropertyPrintingConfig.cs | 0 .../PropertyPrintingConfigExtensions.cs | 0 .../Tests/ObjectPrinterAcceptanceTests.cs | 0 .../Solved => Solved}/Tests/Person.cs | 0 10 files changed, 114 insertions(+), 22 deletions(-) create mode 100644 ObjectPrinting/Extensions/ObjectPrinterExtension.cs rename {ObjectPrinting/Solved => Solved}/ObjectExtensions.cs (100%) rename {ObjectPrinting/Solved => Solved}/ObjectPrinter.cs (100%) rename {ObjectPrinting/Solved => Solved}/PrintingConfig.cs (100%) rename {ObjectPrinting/Solved => Solved}/PropertyPrintingConfig.cs (100%) rename {ObjectPrinting/Solved => Solved}/PropertyPrintingConfigExtensions.cs (100%) rename {ObjectPrinting/Solved => Solved}/Tests/ObjectPrinterAcceptanceTests.cs (100%) rename {ObjectPrinting/Solved => Solved}/Tests/Person.cs (100%) diff --git a/ObjectPrinting/Extensions/ObjectPrinterExtension.cs b/ObjectPrinting/Extensions/ObjectPrinterExtension.cs new file mode 100644 index 00000000..cd5f1544 --- /dev/null +++ b/ObjectPrinting/Extensions/ObjectPrinterExtension.cs @@ -0,0 +1,12 @@ +using System; + +namespace ObjectPrinting.Extensions; + +public static class ObjectPrinterExtension +{ + public static string PrintToString(this T obj) => + ObjectPrinter.For().PrintToString(obj); + + public static string PrintToString(this T obj, Func, PrintingConfig> config) => + config(ObjectPrinter.For()).PrintToString(obj); +} \ No newline at end of file diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index f3c4e738..47ba3f38 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -1,5 +1,5 @@ -using ObjectPrinting.Solved; using System; +using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -13,15 +13,20 @@ public class PrintingConfig { private readonly HashSet excludedTypes = new(); private readonly HashSet excludedProperties = new(); - private readonly Dictionary typeSerializers = new(); - private readonly Dictionary propertySerializers = new(); + private readonly Dictionary typeSerializers = new(); // + private readonly Dictionary propertySerializers = new(); // private readonly Dictionary typeCultures = new(); private readonly Dictionary propertyTrim = new(); - // : + private readonly HashSet finalTypes = + [ + typeof(bool), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), + typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), + typeof(double), typeof(decimal), typeof(string), typeof(DateTime), typeof(TimeSpan), typeof(Guid) + ]; // 1. - public PrintingConfig ExcludePropertiesWithType() + public PrintingConfig Exclude() { excludedTypes.Add(typeof(TPropType)); return this; @@ -48,8 +53,6 @@ public PrintingConfig Exclude(Expression(Expression> propertySelector) { if (propertySelector.Body is MemberExpression memberExpression) diff --git a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs index 4c8b2445..d45afcec 100644 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs @@ -1,4 +1,7 @@ using NUnit.Framework; +using System; +using System.Globalization; +using ObjectPrinting.Extensions; namespace ObjectPrinting.Tests { @@ -10,18 +13,29 @@ public void Demo() { var person = new Person { Name = "Alex", Age = 19 }; - var printer = ObjectPrinter.For(); + var printer = ObjectPrinter.For() //1. Исключить из сериализации свойства определенного типа + .Exclude() //2. Указать альтернативный способ сериализации для определенного типа + .Printing().Using(i => i.ToString("X")) //3. Для числовых типов указать культуру + .Printing().UseCulture(CultureInfo.InvariantCulture) //4. Настроить сериализацию конкретного свойства + .Printing(x => x.Name).Using(p => $"---{p}---") //5. Настроить обрезание строковых свойств (метод должен быть виден только для строковых свойств) + .Printing(p => p.Name).TrimmedToLength(10) //6. Исключить из сериализации конкретного свойства - + .Exclude(p => p.Age); + string s1 = printer.PrintToString(person); + Console.WriteLine(s1); - //7. Синтаксический сахар в виде метода расширения, сериализующего по-умолчанию + //7. Синтаксический сахар в виде метода расширения, сериализующего по-умолчанию + var s2 = person.PrintToString(); + Console.WriteLine(s2); //8. ...с конфигурированием + var s3 = person.PrintToString(p => p.Exclude(x => x.Age)); + Console.WriteLine(s3); } } } \ No newline at end of file diff --git a/ObjectPrinting/Solved/ObjectExtensions.cs b/Solved/ObjectExtensions.cs similarity index 100% rename from ObjectPrinting/Solved/ObjectExtensions.cs rename to Solved/ObjectExtensions.cs diff --git a/ObjectPrinting/Solved/ObjectPrinter.cs b/Solved/ObjectPrinter.cs similarity index 100% rename from ObjectPrinting/Solved/ObjectPrinter.cs rename to Solved/ObjectPrinter.cs diff --git a/ObjectPrinting/Solved/PrintingConfig.cs b/Solved/PrintingConfig.cs similarity index 100% rename from ObjectPrinting/Solved/PrintingConfig.cs rename to Solved/PrintingConfig.cs diff --git a/ObjectPrinting/Solved/PropertyPrintingConfig.cs b/Solved/PropertyPrintingConfig.cs similarity index 100% rename from ObjectPrinting/Solved/PropertyPrintingConfig.cs rename to Solved/PropertyPrintingConfig.cs diff --git a/ObjectPrinting/Solved/PropertyPrintingConfigExtensions.cs b/Solved/PropertyPrintingConfigExtensions.cs similarity index 100% rename from ObjectPrinting/Solved/PropertyPrintingConfigExtensions.cs rename to Solved/PropertyPrintingConfigExtensions.cs diff --git a/ObjectPrinting/Solved/Tests/ObjectPrinterAcceptanceTests.cs b/Solved/Tests/ObjectPrinterAcceptanceTests.cs similarity index 100% rename from ObjectPrinting/Solved/Tests/ObjectPrinterAcceptanceTests.cs rename to Solved/Tests/ObjectPrinterAcceptanceTests.cs diff --git a/ObjectPrinting/Solved/Tests/Person.cs b/Solved/Tests/Person.cs similarity index 100% rename from ObjectPrinting/Solved/Tests/Person.cs rename to Solved/Tests/Person.cs From 49722d458cbbad957729e2543d238c3a3a0821a2 Mon Sep 17 00:00:00 2001 From: Leonid Date: Thu, 12 Dec 2024 00:35:03 +0500 Subject: [PATCH 3/9] Add tests --- ObjectPrinting/ObjectPrinting.csproj | 1 + ObjectPrinting/PrintingConfig.cs | 23 ++- .../Tests/ObjectPrinterAcceptanceTests.cs | 4 +- ObjectPrinting/Tests/ObjectPrinterTests.cs | 163 ++++++++++++++++++ ObjectPrinting/Tests/Person.cs | 11 +- 5 files changed, 194 insertions(+), 8 deletions(-) create mode 100644 ObjectPrinting/Tests/ObjectPrinterTests.cs diff --git a/ObjectPrinting/ObjectPrinting.csproj b/ObjectPrinting/ObjectPrinting.csproj index c5db392f..a5c71017 100644 --- a/ObjectPrinting/ObjectPrinting.csproj +++ b/ObjectPrinting/ObjectPrinting.csproj @@ -5,6 +5,7 @@ + diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 47ba3f38..b07c994b 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -17,6 +17,7 @@ public class PrintingConfig private readonly Dictionary propertySerializers = new(); // private readonly Dictionary typeCultures = new(); private readonly Dictionary propertyTrim = new(); + private int MaxNestingLevel = 5; private readonly HashSet finalTypes = [ @@ -61,6 +62,9 @@ public string PrintToString(TOwner obj) private string PrintToString(object obj, int nestingLevel) { + if (nestingLevel > MaxNestingLevel) + return " "; + if (obj == null) return "null"; @@ -95,9 +99,15 @@ private string PrintToString(object obj, int nestingLevel) if (excludedTypes.Contains(propertyType)) continue; + if (typeSerializers.TryGetValue(propertyType, out var typeSerializer)) + { + sb.AppendLine($"{identation}{propertyName} = {typeSerializer.DynamicInvoke(propertyValue)}"); + continue; + } + if (propertySerializers.TryGetValue(propertyName, out var propertySerializer)) { - sb.AppendLine($"{identation}{propertySerializer.DynamicInvoke(propertyName)} = {propertyValue}"); + sb.AppendLine($"{identation}{propertyName} = {propertySerializer.DynamicInvoke(propertyValue)}"); continue; } @@ -112,7 +122,7 @@ private string PrintToString(object obj, int nestingLevel) if (propertyTrim.TryGetValue(propertyName, out var toTrimLength) && propertyValue is string stringValue) { - sb.AppendLine($"{identation}{propertyName} = {stringValue.Substring(0, Math.Min(stringValue.Length - toTrimLength, stringValue.Length))}"); + sb.AppendLine($"{identation}{propertyName} = {stringValue.Substring(0, Math.Min(toTrimLength, stringValue.Length))}"); continue; } @@ -123,7 +133,7 @@ private string PrintToString(object obj, int nestingLevel) private string SerializeCollection(ICollection collection, int nestingLevel) { - var identation = new string('\t', nestingLevel); + var identation = new string('\t', nestingLevel + 1); var sb = new StringBuilder(); sb.AppendLine("["); @@ -132,8 +142,11 @@ private string SerializeCollection(ICollection collection, int nestingLevel) { foreach (var key in dictionary.Keys) { - sb.Append("{" + PrintToString(key, nestingLevel + 1) + " = "); - sb.Append(PrintToString(dictionary[key], nestingLevel + 1) + "}; "); + sb.Append($"{identation}{{{PrintToString(key, nestingLevel)}: " + + $"{PrintToString(dictionary[key], nestingLevel + 1)}}}"); + + //sb.Append($"{identation}{{{PrintToString(key, nestingLevel)} = "); + //sb.Append(PrintToString(dictionary[key], nestingLevel + 1) + "}; "); } } else diff --git a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs index d45afcec..3dfd0186 100644 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs @@ -11,7 +11,8 @@ public class ObjectPrinterAcceptanceTests [Test] public void Demo() { - var person = new Person { Name = "Alex", Age = 19 }; + //var person = new Person(new Guid(),"Alex",173.65,19); + var person = new Person { Age = 19, Name = "Alex", Height = 173.65, Id = new Guid() }; var printer = ObjectPrinter.For() //1. Исключить из сериализации свойства определенного типа @@ -33,6 +34,7 @@ public void Demo() //7. Синтаксический сахар в виде метода расширения, сериализующего по-умолчанию var s2 = person.PrintToString(); Console.WriteLine(s2); + //8. ...с конфигурированием var s3 = person.PrintToString(p => p.Exclude(x => x.Age)); Console.WriteLine(s3); diff --git a/ObjectPrinting/Tests/ObjectPrinterTests.cs b/ObjectPrinting/Tests/ObjectPrinterTests.cs new file mode 100644 index 00000000..93e4d7ac --- /dev/null +++ b/ObjectPrinting/Tests/ObjectPrinterTests.cs @@ -0,0 +1,163 @@ +using NUnit.Framework; +using System; +using System.Threading.Channels; +using FluentAssertions; +using System.Globalization; +using ObjectPrinting.Extensions; +using System.Collections.Generic; + +namespace ObjectPrinting.Tests; + +[TestFixture] +public class ObjectPrinterTests +{ + private Person person; + + [SetUp] + public void SetUp() + { + //person = new Person(new Guid(), "Alex", 189.25, 19); + person = new Person { Age = 19, Name = "Alex", Height = 173.65, Id = new Guid() }; + } + + [Test] + public void PrintingConfig_Exclude_ShouldExcludeGivenType() + { + var printer = ObjectPrinter.For() + .Exclude(); + + var result = printer.PrintToString(person); + + result.Should().NotContain($"{nameof(person.Id)} = {person.Id}"); + } + + [Test] + public void PrintingConfig_Exclude_ShouldExcludeGivenProperty() + { + var printer = ObjectPrinter.For() + .Exclude(p => p.Name); + + var result = printer.PrintToString(person); + + result.Should().NotContain($"{nameof(person.Name)} = {person.Name}"); + } + + [Test] + public void PrintingConfig_PrintingType_ShouldUseCustomMethod() + { + const string printingType = "int"; + + var printer = ObjectPrinter.For() + .Printing() + .Using(_ => printingType); + + var result = printer.PrintToString(person); + Console.WriteLine("-----------"); + Console.WriteLine(result); + + result.Should().Contain($"{nameof(person.Age)} = {printingType}"); + } + + [Test] + public void PrintingConfig_PrintingUseCulture_ShouldUseGivenCulture() + { + var culture = CultureInfo.CreateSpecificCulture("fr-FR"); + + var printer = ObjectPrinter.For() + .Printing() + .UseCulture(culture); + + var result = printer.PrintToString(person); + + result.Should().Contain($"{nameof(person.Age)} = {person.Age.ToString(culture)}"); + } + + [Test] + public void PrintingConfig_PrintingProperty_ShouldUseCustomMethod() + { + const string printingProperty = "Id"; + + var printer = ObjectPrinter.For() + .Printing(p => p.Id) + .Using(_ => printingProperty); + + var result = printer.PrintToString(person); + + result.Should().Contain($"{nameof(person.Id)} = {printingProperty}"); + } + + [Test] + public void PrintingConfig_PrintingTrim_ShouldReturnTrimmedValue() + { + const int trimLength = 4; + + var printer = ObjectPrinter.For() + .Printing(p => p.Name) + .TrimmedToLength(trimLength); + + var result = printer.PrintToString(person); + + result.Should().Contain($"{nameof(person.Name)} = {person.Name[..trimLength]}"); + } + + [Test] + public void PrintingConfig_ExcludeField_ShouldExcludeGivenProperty() + { + var printer = ObjectPrinter.For() + .Exclude(p => p.Age); + + var result = printer.PrintToString(person); + + result.Should().NotContain($"{nameof(person.Age)} = {person.Age}"); + } + + [Test] + public void PrintingConfig_PrintCycledObject_ShouldNotFail() + { + person.Friend = person; + + var result = person.PrintToString(); + + result.Should().Contain("Достигнут максимум глубины сериализации"); + } + + [Test] + public void PrintToString_PrintClassWithList_ShouldSerializeList() + { + var friends = new List { new(), new() }; + + person.Friends = friends; + + var result = person.PrintToString(); + + result.Should().Contain("["); + result.Should().Contain("]"); + for (var i = 0; i < friends.Count; i++) + { + var friend = friends[i]; + + result.Should().Contain($"\t\t\t{nameof(friend.Id)} = {friend.Id}"); + result.Should().Contain($"\t\t\t{nameof(friend.Name)} = {friend.Name}"); + } + } + + [Test] + public void PrintToString_PrintClassWithDictionary_ShouldSerializeDictionary() + { + var neighbours = new Dictionary + { { 12, new Person() }, { 19, new Person() } }; + + person.Neighbours = neighbours; + + var result = person.PrintToString(); + + foreach (var key in neighbours.Keys) + { + var neighbour = neighbours[key]; + + result.Should().Contain($"\t\t{{{key}: Person"); + result.Should().Contain($"\t\t\t{nameof(neighbour.Id)} = {neighbour.Id}"); + result.Should().Contain($"\t\t\t{nameof(neighbour.Name)} = {neighbour.Name}"); + } + } +} \ No newline at end of file diff --git a/ObjectPrinting/Tests/Person.cs b/ObjectPrinting/Tests/Person.cs index f9555955..955da2a0 100644 --- a/ObjectPrinting/Tests/Person.cs +++ b/ObjectPrinting/Tests/Person.cs @@ -1,12 +1,19 @@ -using System; +using FluentAssertions.Equivalency; +using System; +using System.Collections.Generic; namespace ObjectPrinting.Tests { - public class Person + public class Person//(Guid Id, string Name, double Height, int Age) { public Guid Id { get; set; } public string Name { get; set; } public double Height { get; set; } public int Age { get; set; } + public Person? Friend { get; set; } + + public List? Friends { get; set; } + + public Dictionary? Neighbours { get; set; } } } \ No newline at end of file From 0c24d8e871013bb5614d8e356f66c8438902de06 Mon Sep 17 00:00:00 2001 From: Leonid Date: Tue, 17 Dec 2024 20:11:27 +0500 Subject: [PATCH 4/9] small refactor --- ObjectPrinting/Extensions/CultureExtension.cs | 16 ++++++++++++++++ .../Extensions/NumericCultureExtension.cs | 16 ---------------- .../StringPrintingConfigurationExtension.cs | 2 +- ObjectPrinting/PrintingConfig.cs | 15 ++++++--------- ...ation.cs => PropertyPrintingConfiguration.cs} | 4 ++-- .../Tests/ObjectPrinterAcceptanceTests.cs | 1 - ObjectPrinting/Tests/ObjectPrinterTests.cs | 3 --- ObjectPrinting/Tests/Person.cs | 2 +- 8 files changed, 26 insertions(+), 33 deletions(-) create mode 100644 ObjectPrinting/Extensions/CultureExtension.cs delete mode 100644 ObjectPrinting/Extensions/NumericCultureExtension.cs rename ObjectPrinting/{PrintingConfiguration.cs => PropertyPrintingConfiguration.cs} (82%) diff --git a/ObjectPrinting/Extensions/CultureExtension.cs b/ObjectPrinting/Extensions/CultureExtension.cs new file mode 100644 index 00000000..95e4d3c2 --- /dev/null +++ b/ObjectPrinting/Extensions/CultureExtension.cs @@ -0,0 +1,16 @@ +using System; +using System.Globalization; + +namespace ObjectPrinting.Extensions; + +public static class CultureExtension +{ + public static PrintingConfig UseCulture( + this PropertyPrintingConfiguration propertyStringConfiguration, + CultureInfo culture) where TPropType : IFormattable + { + propertyStringConfiguration.ParentConfig.AddNumericCulture(culture); + + return propertyStringConfiguration.ParentConfig; + } +} \ No newline at end of file diff --git a/ObjectPrinting/Extensions/NumericCultureExtension.cs b/ObjectPrinting/Extensions/NumericCultureExtension.cs deleted file mode 100644 index ced6c4aa..00000000 --- a/ObjectPrinting/Extensions/NumericCultureExtension.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Globalization; - -namespace ObjectPrinting.Extensions; - -public static class NumericCultureExtension -{ - public static PrintingConfig UseCulture( - this PrintingConfiguration propertyStringConfiguration, - CultureInfo culture) where TNumericType : IFormattable - { - propertyStringConfiguration.ParentConfig.AddNumericCulture(culture); - - return propertyStringConfiguration.ParentConfig; - } -} \ No newline at end of file diff --git a/ObjectPrinting/Extensions/StringPrintingConfigurationExtension.cs b/ObjectPrinting/Extensions/StringPrintingConfigurationExtension.cs index 17dbe342..b1a7a089 100644 --- a/ObjectPrinting/Extensions/StringPrintingConfigurationExtension.cs +++ b/ObjectPrinting/Extensions/StringPrintingConfigurationExtension.cs @@ -3,7 +3,7 @@ public static class StringPrintingConfigurationExtension { public static PrintingConfig TrimmedToLength( - this PrintingConfiguration propertyStringConfiguration, int length) + this PropertyPrintingConfiguration propertyStringConfiguration, int length) { propertyStringConfiguration.ParentConfig .AddStringPropertyTrim(propertyStringConfiguration.PropertyMemberInfo.Name, length); diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index b07c994b..78180b04 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -13,8 +13,8 @@ public class PrintingConfig { private readonly HashSet excludedTypes = new(); private readonly HashSet excludedProperties = new(); - private readonly Dictionary typeSerializers = new(); // - private readonly Dictionary propertySerializers = new(); // + private readonly Dictionary typeSerializers = new(); + private readonly Dictionary propertySerializers = new(); private readonly Dictionary typeCultures = new(); private readonly Dictionary propertyTrim = new(); private int MaxNestingLevel = 5; @@ -34,16 +34,16 @@ public PrintingConfig Exclude() } // 2. - public PrintingConfiguration Printing( + public PropertyPrintingConfiguration Printing( Expression> propertySelector) { var memberInfo = GetPropertyName(propertySelector); - return new PrintingConfiguration(this, memberInfo); + return new PropertyPrintingConfiguration(this, memberInfo); } - public PrintingConfiguration Printing() + public PropertyPrintingConfiguration Printing() { - return new PrintingConfiguration(this, null); + return new PropertyPrintingConfiguration(this, null); } // 6. @@ -144,9 +144,6 @@ private string SerializeCollection(ICollection collection, int nestingLevel) { sb.Append($"{identation}{{{PrintToString(key, nestingLevel)}: " + $"{PrintToString(dictionary[key], nestingLevel + 1)}}}"); - - //sb.Append($"{identation}{{{PrintToString(key, nestingLevel)} = "); - //sb.Append(PrintToString(dictionary[key], nestingLevel + 1) + "}; "); } } else diff --git a/ObjectPrinting/PrintingConfiguration.cs b/ObjectPrinting/PropertyPrintingConfiguration.cs similarity index 82% rename from ObjectPrinting/PrintingConfiguration.cs rename to ObjectPrinting/PropertyPrintingConfiguration.cs index aa5bf83e..449c2871 100644 --- a/ObjectPrinting/PrintingConfiguration.cs +++ b/ObjectPrinting/PropertyPrintingConfiguration.cs @@ -3,7 +3,7 @@ namespace ObjectPrinting; -public class PrintingConfiguration +public class PropertyPrintingConfiguration { private readonly PrintingConfig parentConfig; private readonly MemberInfo? propertyMemberInfo; @@ -11,7 +11,7 @@ public class PrintingConfiguration internal PrintingConfig ParentConfig => parentConfig; internal MemberInfo? PropertyMemberInfo => propertyMemberInfo; - public PrintingConfiguration(PrintingConfig parentConfig, MemberInfo? propertyMemberInfo) + public PropertyPrintingConfiguration(PrintingConfig parentConfig, MemberInfo? propertyMemberInfo) { this.parentConfig = parentConfig; this.propertyMemberInfo = propertyMemberInfo; diff --git a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs index 3dfd0186..36037059 100644 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs @@ -11,7 +11,6 @@ public class ObjectPrinterAcceptanceTests [Test] public void Demo() { - //var person = new Person(new Guid(),"Alex",173.65,19); var person = new Person { Age = 19, Name = "Alex", Height = 173.65, Id = new Guid() }; var printer = ObjectPrinter.For() diff --git a/ObjectPrinting/Tests/ObjectPrinterTests.cs b/ObjectPrinting/Tests/ObjectPrinterTests.cs index 93e4d7ac..da619e18 100644 --- a/ObjectPrinting/Tests/ObjectPrinterTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterTests.cs @@ -16,7 +16,6 @@ public class ObjectPrinterTests [SetUp] public void SetUp() { - //person = new Person(new Guid(), "Alex", 189.25, 19); person = new Person { Age = 19, Name = "Alex", Height = 173.65, Id = new Guid() }; } @@ -52,8 +51,6 @@ public void PrintingConfig_PrintingType_ShouldUseCustomMethod() .Using(_ => printingType); var result = printer.PrintToString(person); - Console.WriteLine("-----------"); - Console.WriteLine(result); result.Should().Contain($"{nameof(person.Age)} = {printingType}"); } diff --git a/ObjectPrinting/Tests/Person.cs b/ObjectPrinting/Tests/Person.cs index 955da2a0..d4c3eb89 100644 --- a/ObjectPrinting/Tests/Person.cs +++ b/ObjectPrinting/Tests/Person.cs @@ -4,7 +4,7 @@ namespace ObjectPrinting.Tests { - public class Person//(Guid Id, string Name, double Height, int Age) + public class Person { public Guid Id { get; set; } public string Name { get; set; } From f9c81067c93e74f278b7af22c8916c89c63c65f6 Mon Sep 17 00:00:00 2001 From: Leonid Date: Tue, 17 Dec 2024 20:29:07 +0500 Subject: [PATCH 5/9] change culture serialization --- ObjectPrinting/Extensions/CultureExtension.cs | 2 +- ObjectPrinting/PrintingConfig.cs | 20 ++----------------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/ObjectPrinting/Extensions/CultureExtension.cs b/ObjectPrinting/Extensions/CultureExtension.cs index 95e4d3c2..d8046b9c 100644 --- a/ObjectPrinting/Extensions/CultureExtension.cs +++ b/ObjectPrinting/Extensions/CultureExtension.cs @@ -9,7 +9,7 @@ public static PrintingConfig UseCulture( this PropertyPrintingConfiguration propertyStringConfiguration, CultureInfo culture) where TPropType : IFormattable { - propertyStringConfiguration.ParentConfig.AddNumericCulture(culture); + propertyStringConfiguration.ParentConfig.AddTypeSerializer(t => t.ToString(null, culture)); return propertyStringConfiguration.ParentConfig; } diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 78180b04..f970a8be 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -15,7 +15,6 @@ public class PrintingConfig private readonly HashSet excludedProperties = new(); private readonly Dictionary typeSerializers = new(); private readonly Dictionary propertySerializers = new(); - private readonly Dictionary typeCultures = new(); private readonly Dictionary propertyTrim = new(); private int MaxNestingLevel = 5; @@ -76,11 +75,8 @@ private string PrintToString(object obj, int nestingLevel) if (finalTypes.Contains(obj.GetType())) return obj.ToString(); - if (typeCultures.TryGetValue(type, out var culture) && obj is IFormattable formattable) - return formattable.ToString(null, culture); - if (typeSerializers.TryGetValue(type, out var serializer)) - return serializer.DynamicInvoke(obj).ToString(); + return serializer.DynamicInvoke(obj).ToString(); // if (obj is ICollection collection) return SerializeCollection(collection, nestingLevel); @@ -99,7 +95,7 @@ private string PrintToString(object obj, int nestingLevel) if (excludedTypes.Contains(propertyType)) continue; - if (typeSerializers.TryGetValue(propertyType, out var typeSerializer)) + if (typeSerializers.TryGetValue(propertyType, out var typeSerializer)) // { sb.AppendLine($"{identation}{propertyName} = {typeSerializer.DynamicInvoke(propertyValue)}"); continue; @@ -111,15 +107,6 @@ private string PrintToString(object obj, int nestingLevel) continue; } - if (typeCultures.TryGetValue(propertyType, out var cult)) - { - if (propertyValue is IFormattable format) - { - sb.AppendLine($"{identation}{propertyName} = {format.ToString(null, cult)}"); - continue; - } - } - if (propertyTrim.TryGetValue(propertyName, out var toTrimLength) && propertyValue is string stringValue) { sb.AppendLine($"{identation}{propertyName} = {stringValue.Substring(0, Math.Min(toTrimLength, stringValue.Length))}"); @@ -178,8 +165,5 @@ internal void AddTypeSerializer(Func serializer) = internal void AddStringPropertyTrim(string propertyName, int maxLength) => propertyTrim[propertyName] = maxLength; - - internal void AddNumericCulture(CultureInfo culture) => - typeCultures[typeof(TNumericCulture)] = culture; } } \ No newline at end of file From 6a3a901188bc39ef02360b115db08737a714afdd Mon Sep 17 00:00:00 2001 From: Leonid Date: Tue, 17 Dec 2024 20:37:53 +0500 Subject: [PATCH 6/9] refactor Type/PropertySerializer --- ObjectPrinting/Extensions/CultureExtension.cs | 2 +- ObjectPrinting/PrintingConfig.cs | 16 ++++++++-------- ObjectPrinting/PropertyPrintingConfiguration.cs | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ObjectPrinting/Extensions/CultureExtension.cs b/ObjectPrinting/Extensions/CultureExtension.cs index d8046b9c..ad3deecf 100644 --- a/ObjectPrinting/Extensions/CultureExtension.cs +++ b/ObjectPrinting/Extensions/CultureExtension.cs @@ -9,7 +9,7 @@ public static PrintingConfig UseCulture( this PropertyPrintingConfiguration propertyStringConfiguration, CultureInfo culture) where TPropType : IFormattable { - propertyStringConfiguration.ParentConfig.AddTypeSerializer(t => t.ToString(null, culture)); + propertyStringConfiguration.ParentConfig.AddTypeSerializer(t => ((TPropType)t).ToString(null, culture)); return propertyStringConfiguration.ParentConfig; } diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index f970a8be..187c88e2 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -13,8 +13,8 @@ public class PrintingConfig { private readonly HashSet excludedTypes = new(); private readonly HashSet excludedProperties = new(); - private readonly Dictionary typeSerializers = new(); - private readonly Dictionary propertySerializers = new(); + private readonly Dictionary> typeSerializers = new(); + private readonly Dictionary> propertySerializers = new(); private readonly Dictionary propertyTrim = new(); private int MaxNestingLevel = 5; @@ -76,7 +76,7 @@ private string PrintToString(object obj, int nestingLevel) return obj.ToString(); if (typeSerializers.TryGetValue(type, out var serializer)) - return serializer.DynamicInvoke(obj).ToString(); // + return serializer(obj).ToString(); if (obj is ICollection collection) return SerializeCollection(collection, nestingLevel); @@ -95,15 +95,15 @@ private string PrintToString(object obj, int nestingLevel) if (excludedTypes.Contains(propertyType)) continue; - if (typeSerializers.TryGetValue(propertyType, out var typeSerializer)) // + if (typeSerializers.TryGetValue(propertyType, out var typeSerializer)) { - sb.AppendLine($"{identation}{propertyName} = {typeSerializer.DynamicInvoke(propertyValue)}"); + sb.AppendLine($"{identation}{propertyName} = {typeSerializer(propertyValue)}"); continue; } if (propertySerializers.TryGetValue(propertyName, out var propertySerializer)) { - sb.AppendLine($"{identation}{propertyName} = {propertySerializer.DynamicInvoke(propertyValue)}"); + sb.AppendLine($"{identation}{propertyName} = {propertySerializer(propertyValue)}"); continue; } @@ -157,10 +157,10 @@ private MemberInfo GetPropertyName(Expression throw new ArgumentException("Invalid property selector expression"); } - internal void AddPropertySerializer(string propertyName, Func serializer) => + internal void AddPropertySerializer(string propertyName, Func serializer) => propertySerializers[propertyName] = serializer; - internal void AddTypeSerializer(Func serializer) => + internal void AddTypeSerializer(Func serializer) => typeSerializers[typeof(TPropType)] = serializer; internal void AddStringPropertyTrim(string propertyName, int maxLength) => diff --git a/ObjectPrinting/PropertyPrintingConfiguration.cs b/ObjectPrinting/PropertyPrintingConfiguration.cs index 449c2871..44d068b5 100644 --- a/ObjectPrinting/PropertyPrintingConfiguration.cs +++ b/ObjectPrinting/PropertyPrintingConfiguration.cs @@ -21,11 +21,11 @@ public PrintingConfig Using(Func printingMethod) { if (propertyMemberInfo == null) { - parentConfig.AddTypeSerializer(printingMethod); + parentConfig.AddTypeSerializer(obj => printingMethod((TPropType)obj)); } else { - parentConfig.AddPropertySerializer(propertyMemberInfo.Name, printingMethod); + parentConfig.AddPropertySerializer(propertyMemberInfo.Name, obj => printingMethod((TPropType)obj)); } return parentConfig; From 3f0737b6a0f745880c7bcfea72e496e801864133 Mon Sep 17 00:00:00 2001 From: Leonid Date: Tue, 17 Dec 2024 21:12:55 +0500 Subject: [PATCH 7/9] add SimplePerson for test IEnumerable --- ObjectPrinting/PrintingConfig.cs | 2 +- ObjectPrinting/Tests/ObjectPrinterTests.cs | 20 ++++++++++++-------- ObjectPrinting/Tests/SimplePerson.cs | 13 +++++++++++++ 3 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 ObjectPrinting/Tests/SimplePerson.cs diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 187c88e2..d18d5e8c 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -130,7 +130,7 @@ private string SerializeCollection(ICollection collection, int nestingLevel) foreach (var key in dictionary.Keys) { sb.Append($"{identation}{{{PrintToString(key, nestingLevel)}: " + - $"{PrintToString(dictionary[key], nestingLevel + 1)}}}"); + $"{PrintToString(dictionary[key], nestingLevel + 1)}}}\n"); } } else diff --git a/ObjectPrinting/Tests/ObjectPrinterTests.cs b/ObjectPrinting/Tests/ObjectPrinterTests.cs index da619e18..3e59e9d2 100644 --- a/ObjectPrinting/Tests/ObjectPrinterTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterTests.cs @@ -121,11 +121,13 @@ public void PrintingConfig_PrintCycledObject_ShouldNotFail() [Test] public void PrintToString_PrintClassWithList_ShouldSerializeList() { - var friends = new List { new(), new() }; + var friends = new List { new(), new() }; - person.Friends = friends; + SimplePerson simplePerson = new SimplePerson() { Name = "Alex", Id = new Guid() }; - var result = person.PrintToString(); + simplePerson.Friends = friends; + + var result = simplePerson.PrintToString(); result.Should().Contain("["); result.Should().Contain("]"); @@ -141,18 +143,20 @@ public void PrintToString_PrintClassWithList_ShouldSerializeList() [Test] public void PrintToString_PrintClassWithDictionary_ShouldSerializeDictionary() { - var neighbours = new Dictionary - { { 12, new Person() }, { 19, new Person() } }; + var neighbours = new Dictionary + { { 12, new SimplePerson() }, { 19, new SimplePerson() } }; - person.Neighbours = neighbours; + SimplePerson simplePerson = new SimplePerson() { Name = "Alex", Id = new Guid() }; - var result = person.PrintToString(); + simplePerson.Neighbours = neighbours; + + var result = simplePerson.PrintToString(); foreach (var key in neighbours.Keys) { var neighbour = neighbours[key]; - result.Should().Contain($"\t\t{{{key}: Person"); + result.Should().Contain($"\t\t{{{key}: SimplePerson"); result.Should().Contain($"\t\t\t{nameof(neighbour.Id)} = {neighbour.Id}"); result.Should().Contain($"\t\t\t{nameof(neighbour.Name)} = {neighbour.Name}"); } diff --git a/ObjectPrinting/Tests/SimplePerson.cs b/ObjectPrinting/Tests/SimplePerson.cs new file mode 100644 index 00000000..a744d7f9 --- /dev/null +++ b/ObjectPrinting/Tests/SimplePerson.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace ObjectPrinting.Tests; + +public class SimplePerson +{ + public Guid Id { get; set; } + public string Name { get; set; } + + public List? Friends { get; set; } + public Dictionary? Neighbours { get; set; } +} \ No newline at end of file From 731d1a738bdc9990f7a912bbb114d358d1bd861a Mon Sep 17 00:00:00 2001 From: Leonid Date: Tue, 17 Dec 2024 21:58:26 +0500 Subject: [PATCH 8/9] Add more tests --- ObjectPrinting/PrintingConfig.cs | 18 ++++- ObjectPrinting/Tests/ObjectPrinterTests.cs | 82 +++++++++++++++++++++- ObjectPrinting/Tests/Person.cs | 1 + 3 files changed, 97 insertions(+), 4 deletions(-) diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index d18d5e8c..b8d9908b 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -16,13 +16,27 @@ public class PrintingConfig private readonly Dictionary> typeSerializers = new(); private readonly Dictionary> propertySerializers = new(); private readonly Dictionary propertyTrim = new(); - private int MaxNestingLevel = 5; + private int maxNestingLevel = 5; + + public int MaxNestingLevel + { + get => maxNestingLevel; + private set + { + if (value <= 0) + { + throw new ArgumentOutOfRangeException( + nameof(value), value, "The maxNestingDepth value must be positive."); + } + maxNestingLevel = value; + } + } private readonly HashSet finalTypes = [ typeof(bool), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), - typeof(double), typeof(decimal), typeof(string), typeof(DateTime), typeof(TimeSpan), typeof(Guid) + typeof(double), typeof(decimal), typeof(string), typeof(TimeSpan), typeof(Guid) // , typeof(DateTime) ]; // 1. diff --git a/ObjectPrinting/Tests/ObjectPrinterTests.cs b/ObjectPrinting/Tests/ObjectPrinterTests.cs index 3e59e9d2..412e45c2 100644 --- a/ObjectPrinting/Tests/ObjectPrinterTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterTests.cs @@ -1,6 +1,5 @@ using NUnit.Framework; using System; -using System.Threading.Channels; using FluentAssertions; using System.Globalization; using ObjectPrinting.Extensions; @@ -16,7 +15,14 @@ public class ObjectPrinterTests [SetUp] public void SetUp() { - person = new Person { Age = 19, Name = "Alex", Height = 173.65, Id = new Guid() }; + person = new Person + { + Age = 19, + Name = "Alex", + Height = 173.65, + Id = new Guid(), + DateOfBirth = new DateTime(1978, 6, 19) + }; } [Test] @@ -30,6 +36,78 @@ public void PrintingConfig_Exclude_ShouldExcludeGivenType() result.Should().NotContain($"{nameof(person.Id)} = {person.Id}"); } + [Test] + public void PrintingConfig_ExcludeAndAddSerialization_ShouldExcludeGivenType() + { + var printer = ObjectPrinter.For() + .Exclude() + .Printing().Using(_ => "XXX"); + + var result = printer.PrintToString(person); + + result.Should().NotContain($"{nameof(person.Name)} = XXX"); + } + + [Test] + public void PrintingConfig_AddSerializationAndExclude_ShouldExcludeGivenType() + { + var printer = ObjectPrinter.For() + .Printing().Using(_ => "XXX") + .Exclude(); + + var result = printer.PrintToString(person); + + result.Should().NotContain($"{nameof(person.Name)} = XXX"); + } + + [Test] + public void PrintingConfig_ExcludeCollection_ShouldExcludeGivenType() + { + var printer = ObjectPrinter.For() + .Exclude>(); + + var result = printer.PrintToString(person); + + result.Should().NotContain($"{nameof(person.Friends)}"); + } + + [Test] + public void PrintingConfig_ExcludeSomeTypes_ShouldExcludeGivenTypes() + { + var printer = ObjectPrinter.For() + .Exclude() + .Exclude(); + + var result = printer.PrintToString(person); + + result.Should().NotContain($"{nameof(person.Id)} = {person.Id}"); + result.Should().NotContain($"{nameof(person.Age)} = {person.Age}"); + } + + [Test] + public void PrintingConfig_ExcludeTypeSeveralTimes_ShouldExcludeGivenType() + { + var printer = ObjectPrinter.For() + .Exclude() + .Exclude(); + + var result = printer.PrintToString(person); + + result.Should().NotContain($"{nameof(person.Id)} = {person.Id}"); + } + + [Test] + public void PrintingConfig_CorrectWorksWithTime() + { + var printer = ObjectPrinter.For() + .Printing(p => p.DateOfBirth) + .Using(x => x.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture)); + + var result = printer.PrintToString(person); + + result.Should().Contain($"{nameof(person.DateOfBirth)} = 19/06/1978"); + } + [Test] public void PrintingConfig_Exclude_ShouldExcludeGivenProperty() { diff --git a/ObjectPrinting/Tests/Person.cs b/ObjectPrinting/Tests/Person.cs index d4c3eb89..eac9e539 100644 --- a/ObjectPrinting/Tests/Person.cs +++ b/ObjectPrinting/Tests/Person.cs @@ -10,6 +10,7 @@ public class Person public string Name { get; set; } public double Height { get; set; } public int Age { get; set; } + public DateTime DateOfBirth { get; set; } public Person? Friend { get; set; } public List? Friends { get; set; } From 7c207b807d502d7cffc8d5ba29ad2919996b94a1 Mon Sep 17 00:00:00 2001 From: Leonid Date: Tue, 17 Dec 2024 22:05:16 +0500 Subject: [PATCH 9/9] small refactor --- ObjectPrinting/PrintingConfig.cs | 7 ++----- ObjectPrinting/Tests/ObjectPrinterTests.cs | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index b8d9908b..2f16a9b1 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -36,17 +36,15 @@ private set [ typeof(bool), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), - typeof(double), typeof(decimal), typeof(string), typeof(TimeSpan), typeof(Guid) // , typeof(DateTime) + typeof(double), typeof(decimal), typeof(string), typeof(DateTime), typeof(TimeSpan), typeof(Guid) ]; - // 1. public PrintingConfig Exclude() { excludedTypes.Add(typeof(TPropType)); return this; } - // 2. public PropertyPrintingConfiguration Printing( Expression> propertySelector) { @@ -59,7 +57,6 @@ public PropertyPrintingConfiguration Printing() return new PropertyPrintingConfiguration(this, null); } - // 6. public PrintingConfig Exclude(Expression> propertySelector) { var propertyName = GetPropertyName(propertySelector); @@ -76,7 +73,7 @@ public string PrintToString(TOwner obj) private string PrintToString(object obj, int nestingLevel) { if (nestingLevel > MaxNestingLevel) - return " "; + return "Maximum serialization depth has been reached"; if (obj == null) return "null"; diff --git a/ObjectPrinting/Tests/ObjectPrinterTests.cs b/ObjectPrinting/Tests/ObjectPrinterTests.cs index 412e45c2..930a4d49 100644 --- a/ObjectPrinting/Tests/ObjectPrinterTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterTests.cs @@ -193,7 +193,7 @@ public void PrintingConfig_PrintCycledObject_ShouldNotFail() var result = person.PrintToString(); - result.Should().Contain("Достигнут максимум глубины сериализации"); + result.Should().Contain("Maximum serialization depth has been reached"); } [Test]