From 1007a223576a24798abd1a94f2938e243828dae6 Mon Sep 17 00:00:00 2001 From: kexogg Date: Thu, 12 Dec 2024 03:51:16 +0500 Subject: [PATCH 1/6] homework --- .../MemberPrintingConfingExtentions.cs | 17 ++ ObjectPrinting/Extensions/ObjectExtentions.cs | 10 + ObjectPrinting/IMemberPrintingConfig.cs | 12 ++ ObjectPrinting/IPrintingConifg.cs | 18 ++ ObjectPrinting/MemberPrintingConfig.cs | 27 +++ ObjectPrinting/ObjectPrinting.csproj | 2 +- ObjectPrinting/PrintingConfig.cs | 186 ++++++++++++++++-- .../Tests/ObjectPrinterAcceptanceTests.cs | 25 ++- .../ObjectPrinter_Should_HandleRecursion.txt | 6 + .../ObjectPrinter_Should_SerializeArray.txt | 10 + ...jectPrinter_Should_SerializeCollection.txt | 10 + ...jectPrinter_Should_SerializeDictionary.txt | 3 + .../ObjectPrinter_Should_SerializeObject.txt | 5 + ...ct_WithAlternativeSerializationForType.txt | 5 + ...thAlternativeSerialization_ForProperty.txt | 5 + ..._SerializeObject_WithCultureSetForProp.txt | 5 + ..._SerializeObject_WithCultureSetForType.txt | 5 + ...alizeObject_WithExcludedNestedProperty.txt | 10 + ...d_SerializeObject_WithExcludedProperty.txt | 4 + ...hould_SerializeObject_WithExcludedType.txt | 4 + ...rinter_Should_SerializeObject_WithTrim.txt | 5 + ObjectPrintingTests/Models/Person.cs | 20 ++ ObjectPrintingTests/ObjectPrinterTests.cs | 181 +++++++++++++++++ .../ObjectPrintingTests.csproj | 34 ++++ fluent-api.sln | 6 + fluent-api.sln.DotSettings | 3 + 26 files changed, 596 insertions(+), 22 deletions(-) create mode 100644 ObjectPrinting/Extensions/MemberPrintingConfingExtentions.cs create mode 100644 ObjectPrinting/Extensions/ObjectExtentions.cs create mode 100644 ObjectPrinting/IMemberPrintingConfig.cs create mode 100644 ObjectPrinting/IPrintingConifg.cs create mode 100644 ObjectPrinting/MemberPrintingConfig.cs create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_HandleRecursion.txt create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeArray.txt create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeCollection.txt create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeDictionary.txt create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject.txt create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerializationForType.txt create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForProperty.txt create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSetForProp.txt create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSetForType.txt create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedNestedProperty.txt create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedProperty.txt create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedType.txt create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithTrim.txt create mode 100644 ObjectPrintingTests/Models/Person.cs create mode 100644 ObjectPrintingTests/ObjectPrinterTests.cs create mode 100644 ObjectPrintingTests/ObjectPrintingTests.csproj diff --git a/ObjectPrinting/Extensions/MemberPrintingConfingExtentions.cs b/ObjectPrinting/Extensions/MemberPrintingConfingExtentions.cs new file mode 100644 index 00000000..e8f438b9 --- /dev/null +++ b/ObjectPrinting/Extensions/MemberPrintingConfingExtentions.cs @@ -0,0 +1,17 @@ +using System; + +namespace ObjectPrinting.Extensions; + +public static class MemberPrintingConfigExtensions +{ + public static string PrintToString(this T obj, Func, IPrintingConfig> config) + { + return config(ObjectPrinter.For()).PrintToString(obj); + } + + public static IPrintingConfig TrimmedToLength(this MemberPrintingConfig propConfig, + int maxLen) + { + return ((IMemberPrintingConfig)propConfig).Config; + } +} \ No newline at end of file diff --git a/ObjectPrinting/Extensions/ObjectExtentions.cs b/ObjectPrinting/Extensions/ObjectExtentions.cs new file mode 100644 index 00000000..0cc8616a --- /dev/null +++ b/ObjectPrinting/Extensions/ObjectExtentions.cs @@ -0,0 +1,10 @@ +namespace ObjectPrinting.Extensions +{ + 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/IMemberPrintingConfig.cs b/ObjectPrinting/IMemberPrintingConfig.cs new file mode 100644 index 00000000..250f9610 --- /dev/null +++ b/ObjectPrinting/IMemberPrintingConfig.cs @@ -0,0 +1,12 @@ +using System; +using System.Linq.Expressions; + +namespace ObjectPrinting; + +public interface IMemberPrintingConfig +{ + IPrintingConfig Config { get; } + + IPrintingConfig With(Func serializer); + IPrintingConfig With(Expression> expression, Func serializer); +} \ No newline at end of file diff --git a/ObjectPrinting/IPrintingConifg.cs b/ObjectPrinting/IPrintingConifg.cs new file mode 100644 index 00000000..0cedd895 --- /dev/null +++ b/ObjectPrinting/IPrintingConifg.cs @@ -0,0 +1,18 @@ +using System; +using System.Globalization; +using System.Linq.Expressions; + +namespace ObjectPrinting; + +public interface IPrintingConfig +{ + IPrintingConfig Exclude(); + IPrintingConfig Exclude(Expression> expression); + IMemberPrintingConfig Serialize(); + IMemberPrintingConfig Serialize(Expression> expression); + IPrintingConfig SetCultureFor(CultureInfo cultureInfo); + IPrintingConfig SetCultureFor(Expression> expression, CultureInfo cultureInfo); + IPrintingConfig TrimString(Expression> expression, int length); + string PrintToString(TOwner obj); +} + diff --git a/ObjectPrinting/MemberPrintingConfig.cs b/ObjectPrinting/MemberPrintingConfig.cs new file mode 100644 index 00000000..9132d1a3 --- /dev/null +++ b/ObjectPrinting/MemberPrintingConfig.cs @@ -0,0 +1,27 @@ +using System; +using System.Linq.Expressions; + +namespace ObjectPrinting; + +public class MemberPrintingConfig : IMemberPrintingConfig +{ + private readonly PrintingConfig config; + public MemberPrintingConfig(PrintingConfig printingConfig) + { + config = printingConfig; + } + + public IPrintingConfig Config => config; + + public IPrintingConfig With(Func serializer) + { + config.AlternativeSerializationForType.Add(typeof(TFieldType), o => serializer((TFieldType)o)); + return config; + } + + public IPrintingConfig With(Expression> expression, Func serializer) + { + config.AlternativeSerializationForProp.Add(PrintingConfig.GetPropDetails(expression), o => serializer((TFieldType)o)); + return config; + } +} \ No newline at end of file diff --git a/ObjectPrinting/ObjectPrinting.csproj b/ObjectPrinting/ObjectPrinting.csproj index c5db392f..aa9b2915 100644 --- a/ObjectPrinting/ObjectPrinting.csproj +++ b/ObjectPrinting/ObjectPrinting.csproj @@ -1,6 +1,6 @@  - net8.0 + net9.0 enable diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index a9e08211..70fcd4b5 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -1,41 +1,197 @@ 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.Extensions; namespace ObjectPrinting { - public class PrintingConfig + public class PrintingConfig : IPrintingConfig { + private readonly HashSet simpleTypes = + [ + typeof(bool), typeof(byte), typeof(int), typeof(double), typeof(float), typeof(char), typeof(string), + typeof(DateTime), typeof(TimeSpan), typeof(Guid) + ]; + private readonly HashSet excludedTypes = new(); + private readonly HashSet excludedProps = new(); + private readonly HashSet alreadyProcessed = new(ReferenceEqualityComparer.Instance); + private readonly Dictionary cultureForType = new(); + private readonly Dictionary cultureForProp = new(); + private readonly Dictionary trimLengthForProp = new(); + private PropertyInfo? currentProp; + + protected internal readonly Dictionary> + AlternativeSerializationForProp = new(); + + protected internal readonly Dictionary> AlternativeSerializationForType = new(); + public string PrintToString(TOwner obj) { return PrintToString(obj, 0); } - private string PrintToString(object obj, int nestingLevel) + protected internal static MemberInfo GetPropDetails(Expression> expression) + { + return expression.Body switch + { + MemberExpression memberExpression => memberExpression.Member, + UnaryExpression { Operand: MemberExpression operand } => operand.Member, + _ => throw new ArgumentException("Expression is not a property") + }; + } + + private string PrintToString(object? obj, int nestingLevel) { - //TODO apply configurations if (obj == null) - return "null" + Environment.NewLine; + return string.Empty; + if (alreadyProcessed.Contains(obj)) + return "[Recursion]"; + if (TryProcessSimpleType(obj, out var result)) + return result; + if (TryProcessCollection(obj, nestingLevel, out result)) + return result; + if (TryProcessDictionary(obj, nestingLevel, out result)) + return result; + return ProcessNestedObject(obj, nestingLevel); + } - var finalTypes = new[] + private bool TryProcessSimpleType(object obj, out string result) + { + var type = obj.GetType(); + if (simpleTypes.Contains(type)) { - typeof(int), typeof(double), typeof(float), typeof(string), - typeof(DateTime), typeof(TimeSpan) - }; - if (finalTypes.Contains(obj.GetType())) - return obj + Environment.NewLine; + result = (obj switch + { + IFormattable f when currentProp != null && cultureForProp.TryGetValue(currentProp, out var culture) => f.ToString(null, culture), + IFormattable f when cultureForType.ContainsKey(type) => f.ToString(null, cultureForType[type]), + _ => obj.ToString() + })!; + + if (currentProp != null && trimLengthForProp.TryGetValue(currentProp, out var length)) + result = result.Length > length ? result[..length] : result; + + return true; + } + + result = string.Empty; + return false; + } + + private bool TryProcessCollection(object obj, int nestingLevel, out string result) + { + if (obj is IEnumerable collection) + { + var sb = new StringBuilder(); + foreach (var item in collection) + sb.Append(PrintToString(item, nestingLevel)); + result = sb.ToString(); + return true; + } + + result = string.Empty; + return false; + } + + private bool TryProcessDictionary(object obj, int nestingLevel, out string result) + { + if (obj is IDictionary dictionary) + { + var sb = new StringBuilder(); + sb.Append('\t', nestingLevel); + sb.AppendLine(obj.GetType().Name); + foreach (DictionaryEntry entry in dictionary) + { + var key = entry.Key; + var value = entry.Value; + sb.Append('\t', nestingLevel + 1); + sb.AppendLine($"{key.PrintToString()} = {value.PrintToString()}"); + } + result = sb.ToString(); + return true; + } + + result = string.Empty; + return false; + } - var identation = new string('\t', nestingLevel + 1); + private string ProcessNestedObject(object obj, int nestingLevel) + { + alreadyProcessed.Add(obj); var sb = new StringBuilder(); var type = obj.GetType(); sb.AppendLine(type.Name); - foreach (var propertyInfo in type.GetProperties()) + + foreach (var property in type.GetProperties()) { - sb.Append(identation + propertyInfo.Name + " = " + - PrintToString(propertyInfo.GetValue(obj), - nestingLevel + 1)); + currentProp = property; + if (excludedTypes.Contains(property.PropertyType) || excludedProps.Contains(property)) + continue; + var serializedValue = Serialize(property, obj, nestingLevel + 1); + sb.Append('\t', nestingLevel + 1); + sb.AppendLine($"{property.Name} = {serializedValue}"); } + currentProp = null; + return sb.ToString(); } + + private string Serialize(PropertyInfo property, object parent, int nestingLevel) + { + var value = property.GetValue(parent); + if (value == null) + return "null"; + if (AlternativeSerializationForProp.TryGetValue(property, out var propertySerializer)) + return propertySerializer(value); + if (AlternativeSerializationForType.TryGetValue(property.PropertyType, out var typeSerializer)) + return typeSerializer(value); + return PrintToString(value, nestingLevel); + } + + public IPrintingConfig Exclude() + { + excludedTypes.Add(typeof(TFieldType)); + return this; + } + + public IPrintingConfig Exclude(Expression> expression) + { + excludedProps.Add(GetPropDetails(expression)); + return this; + } + + public IMemberPrintingConfig Serialize() + { + return new MemberPrintingConfig(this); + } + + public IMemberPrintingConfig Serialize( + Expression> expression) + { + return new MemberPrintingConfig(this); + } + + public IPrintingConfig SetCultureFor(CultureInfo cultureInfo) + { + cultureForType.Add(typeof(TFieldType), cultureInfo); + return this; + } + + public IPrintingConfig SetCultureFor(Expression> expression, + CultureInfo cultureInfo) + { + cultureForProp.Add(GetPropDetails(expression), cultureInfo); + return this; + } + + public IPrintingConfig TrimString(Expression> expression, int length) + { + trimLengthForProp.Add(GetPropDetails(expression), length); + return this; + } } } \ No newline at end of file diff --git a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs index 4c8b2445..203d12e1 100644 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs @@ -1,4 +1,7 @@ -using NUnit.Framework; +using System; +using System.Globalization; +using NUnit.Framework; +using ObjectPrinting.Extensions; namespace ObjectPrinting.Tests { @@ -8,20 +11,30 @@ public class ObjectPrinterAcceptanceTests [Test] public void Demo() { - var person = new Person { Name = "Alex", Age = 19 }; + var person = new Person { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }; - var printer = ObjectPrinter.For(); + var printer = ObjectPrinter.For() //1. Исключить из сериализации свойства определенного типа + .Exclude() //2. Указать альтернативный способ сериализации для определенного типа + .Serialize().With(str => str.ToUpper()) //3. Для числовых типов указать культуру + .SetCultureFor(CultureInfo.InvariantCulture) //4. Настроить сериализацию конкретного свойства + .Serialize(p => p.Name).With(name => name.ToUpper()) //5. Настроить обрезание строковых свойств (метод должен быть виден только для строковых свойств) + .TrimString(p => p.Name, 10) //6. Исключить из сериализации конкретного свойства - - string s1 = printer.PrintToString(person); + .Exclude(p => p.Age) + ; - //7. Синтаксический сахар в виде метода расширения, сериализующего по-умолчанию + var s1 = printer.PrintToString(person); + Console.WriteLine(s1); + Assert.Pass(); + //7. Синтаксический сахар в виде метода расширения, сериализующего по-умолчанию + person.PrintToString(); //8. ...с конфигурированием + person.PrintToString(c => c.Exclude(p => p.Age)); } } } \ No newline at end of file diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_HandleRecursion.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_HandleRecursion.txt new file mode 100644 index 00000000..1c69f056 --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_HandleRecursion.txt @@ -0,0 +1,6 @@ +Child + Parent = [Recursion] + Id = 00000000-0000-0000-0000-000000000000 + Name = Alex + Height = 180 + Age = 19 diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeArray.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeArray.txt new file mode 100644 index 00000000..003bdb79 --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeArray.txt @@ -0,0 +1,10 @@ +Person + Id = 00000000-0000-0000-0000-000000000000 + Name = Alex + Height = 180 + Age = 19 +Person + Id = 00000000-0000-0000-0000-000000000000 + Name = John + Height = 190 + Age = 20 diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeCollection.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeCollection.txt new file mode 100644 index 00000000..003bdb79 --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeCollection.txt @@ -0,0 +1,10 @@ +Person + Id = 00000000-0000-0000-0000-000000000000 + Name = Alex + Height = 180 + Age = 19 +Person + Id = 00000000-0000-0000-0000-000000000000 + Name = John + Height = 190 + Age = 20 diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeDictionary.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeDictionary.txt new file mode 100644 index 00000000..760490cd --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeDictionary.txt @@ -0,0 +1,3 @@ +Dictionary`2 + one = 1 + two = 2 diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject.txt new file mode 100644 index 00000000..9466419f --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject.txt @@ -0,0 +1,5 @@ +Person + Id = 00000000-0000-0000-0000-000000000000 + Name = Alex + Height = 180.5 + Age = 19 diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerializationForType.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerializationForType.txt new file mode 100644 index 00000000..57d98d35 --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerializationForType.txt @@ -0,0 +1,5 @@ +Person + Id = 00000000-0000-0000-0000-000000000000 + Name = Alex + Height = 180.00 + Age = 19 diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForProperty.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForProperty.txt new file mode 100644 index 00000000..48e0a447 --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForProperty.txt @@ -0,0 +1,5 @@ +Person + Id = 00000000-0000-0000-0000-000000000000 + Name = ALEX + Height = 180 + Age = 19 diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSetForProp.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSetForProp.txt new file mode 100644 index 00000000..71a3dd61 --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSetForProp.txt @@ -0,0 +1,5 @@ +Person + Id = 00000000-0000-0000-0000-000000000000 + Name = Alex + Height = 180,5 + Age = 19 diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSetForType.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSetForType.txt new file mode 100644 index 00000000..71a3dd61 --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSetForType.txt @@ -0,0 +1,5 @@ +Person + Id = 00000000-0000-0000-0000-000000000000 + Name = Alex + Height = 180,5 + Age = 19 diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedNestedProperty.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedNestedProperty.txt new file mode 100644 index 00000000..2e8637e4 --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedNestedProperty.txt @@ -0,0 +1,10 @@ +Child + Parent = Person + Id = 00000000-0000-0000-0000-000000000000 + Height = 190 + Age = 50 + + Id = 00000000-0000-0000-0000-000000000000 + Name = Alex + Height = 180 + Age = 19 diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedProperty.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedProperty.txt new file mode 100644 index 00000000..4915250f --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedProperty.txt @@ -0,0 +1,4 @@ +Person + Id = 00000000-0000-0000-0000-000000000000 + Height = 180 + Age = 19 diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedType.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedType.txt new file mode 100644 index 00000000..5505cb33 --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedType.txt @@ -0,0 +1,4 @@ +Person + Id = 00000000-0000-0000-0000-000000000000 + Name = Alex + Age = 19 diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithTrim.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithTrim.txt new file mode 100644 index 00000000..608cd2a2 --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithTrim.txt @@ -0,0 +1,5 @@ +Person + Id = 00000000-0000-0000-0000-000000000000 + Name = Al + Height = 180 + Age = 19 diff --git a/ObjectPrintingTests/Models/Person.cs b/ObjectPrintingTests/Models/Person.cs new file mode 100644 index 00000000..ebe0d74b --- /dev/null +++ b/ObjectPrintingTests/Models/Person.cs @@ -0,0 +1,20 @@ +namespace ObjectPrintingTests.Models +{ + public class Person + { + public Guid Id { get; set; } + public string Name { get; set; } + public double Height { get; set; } + public int Age { get; set; } + } + + public class Child : Person + { + public Person Parent { get; set; } + } + + public class SkilledPerson : Person + { + public Dictionary Skills { get; set; } + } +} \ No newline at end of file diff --git a/ObjectPrintingTests/ObjectPrinterTests.cs b/ObjectPrintingTests/ObjectPrinterTests.cs new file mode 100644 index 00000000..ac01a899 --- /dev/null +++ b/ObjectPrintingTests/ObjectPrinterTests.cs @@ -0,0 +1,181 @@ +using System.Globalization; +using FluentAssertions; +using ObjectPrinting; +using ObjectPrintingTests.Models; + +namespace ObjectPrintingTests; + +public class ObjectPrinterTests +{ + private string expectedString; + [SetUp] + public void Setup() + { + expectedString = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + } + + [Test] + public void ObjectPrinter_Should_SerializeObject() + { + var person = new Person { Name = "Alex", Age = 19, Height = 180.5, Id = new Guid() }; + + var printer = ObjectPrinter.For(); + + printer.PrintToString(person).Should() + .Be(expectedString); + } + + [Test] + public void ObjectPrinter_Should_SerializeObject_WithCultureSetForProp() + { + var person = new Person { Name = "Alex", Age = 19, Height = 180.5, Id = new Guid() }; + + var printer = ObjectPrinter.For() + .SetCultureFor(p => p.Height, CultureInfo.GetCultureInfo("ru-RU")); + + printer.PrintToString(person).Should() + .Be(expectedString); + } + + [Test] + public void ObjectPrinter_Should_SerializeObject_WithCultureSetForType() + { + var person = new Person { Name = "Alex", Age = 19, Height = 180.5, Id = new Guid() }; + + var printer = ObjectPrinter.For() + .SetCultureFor(CultureInfo.GetCultureInfo("ru-RU")); + + printer.PrintToString(person).Should() + .Be(expectedString); + } + + [Test] + public void ObjectPrinter_Should_SerializeObject_WithTrim() + { + var person = new Person { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }; + + var printer = ObjectPrinter.For() + .TrimString(p => p.Name, 2); + + printer.PrintToString(person).Should() + .Be(expectedString); + } + + [Test] + public void ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForProperty() + { + var person = new Person { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }; + + var printer = ObjectPrinter.For() + .Serialize(p => p.Name).With(name => name.ToUpper()); + + printer.PrintToString(person).Should() + .Be(expectedString); + } + + [Test] + public void ObjectPrinter_Should_SerializeObject_WithAlternativeSerializationForType() + { + var person = new Person { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }; + + var printer = ObjectPrinter.For() + .Serialize().With(d => d.ToString("F2")) + ; + + printer.PrintToString(person).Should() + .Be(expectedString); + } + + [Test] + public void ObjectPrinter_Should_SerializeObject_WithExcludedType() + { + var person = new Person { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }; + + var printer = ObjectPrinter.For() + .Exclude(); + + printer.PrintToString(person).Should() + .Be(expectedString); + } + + [Test] + public void ObjectPrinter_Should_SerializeObject_WithExcludedProperty() + { + var person = new Person { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }; + + var printer = ObjectPrinter.For() + .Exclude(p => p.Name); + + printer.PrintToString(person).Should() + .Be(expectedString); + } + + [Test] + public void ObjectPrinter_Should_SerializeObject_WithExcludedNestedProperty() + { + var person = new Child() + { + Name = "Alex", Age = 19, Height = 180, Id = new Guid(), + Parent = new Person { Name = "John", Age = 50, Height = 190, Id = new Guid() } + }; + var printer = ObjectPrinter.For() + .Exclude(p => p.Parent.Name); + printer.PrintToString(person).Should() + .Be(expectedString); + } + + [Test] + public void ObjectPrinter_Should_SerializeCollection() + { + var persons = new List + { + new() { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }, + new() { Name = "John", Age = 20, Height = 190, Id = new Guid() } + }; + + var printer = ObjectPrinter.For>(); + + printer.PrintToString(persons).Should() + .Be( + expectedString); + } + [Test] + public void ObjectPrinter_Should_SerializeDictionary() + { + var dictionary = new Dictionary + { + { "one", 1 }, + { "two", 2 } + }; + var printer = ObjectPrinter.For>(); + printer.PrintToString(dictionary).Should() + .Be(expectedString); + } + + [Test] + public void ObjectPrinter_Should_HandleRecursion() + { + var child = new Child() + { + Name = "Alex", Age = 19, Height = 180, Id = new Guid(), + }; + child.Parent = child; + var printer = ObjectPrinter.For(); + printer.PrintToString(child).Should() + .Be(expectedString); + } + + [Test] + public void ObjectPrinter_Should_SerializeArray() + { + var people = new Person[] + { + new() { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }, + new() { Name = "John", Age = 20, Height = 190, Id = new Guid() } + }; + var printer = ObjectPrinter.For(); + printer.PrintToString(people).Should() + .Be(expectedString); + } + +} \ No newline at end of file diff --git a/ObjectPrintingTests/ObjectPrintingTests.csproj b/ObjectPrintingTests/ObjectPrintingTests.csproj new file mode 100644 index 00000000..443d6e95 --- /dev/null +++ b/ObjectPrintingTests/ObjectPrintingTests.csproj @@ -0,0 +1,34 @@ + + + + net9.0 + latest + enable + enable + false + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/fluent-api.sln b/fluent-api.sln index 69c8db9e..4f1a9fae 100644 --- a/fluent-api.sln +++ b/fluent-api.sln @@ -13,6 +13,8 @@ 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("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObjectPrintingTests", "ObjectPrintingTests\ObjectPrintingTests.csproj", "{F12184C9-493B-422F-8466-D1F569627CC6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -35,6 +37,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 + {F12184C9-493B-422F-8466-D1F569627CC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F12184C9-493B-422F-8466-D1F569627CC6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F12184C9-493B-422F-8466-D1F569627CC6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F12184C9-493B-422F-8466-D1F569627CC6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/fluent-api.sln.DotSettings b/fluent-api.sln.DotSettings index 135b83ec..53fe49b2 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" WarnAboutPrefixesAndSuffixes="False" 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" WarnAboutPrefixesAndSuffixes="False" Prefix="" Suffix="" Style="AaBb_AaBb" /></Policy> + True True True Imported 10.10.2016 From 5155db6395d5d6ccf12fc7fa3d8e7c3bb532b84f Mon Sep 17 00:00:00 2001 From: kexogg Date: Thu, 12 Dec 2024 17:09:47 +0500 Subject: [PATCH 2/6] acceptance tests fix --- ObjectPrinting/IMemberPrintingConfig.cs | 3 +-- ObjectPrinting/MemberPrintingConfig.cs | 18 +++++++++++------- ObjectPrinting/PrintingConfig.cs | 2 +- .../Tests/ObjectPrinterAcceptanceTests.cs | 15 +++++++-------- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/ObjectPrinting/IMemberPrintingConfig.cs b/ObjectPrinting/IMemberPrintingConfig.cs index 250f9610..a040db18 100644 --- a/ObjectPrinting/IMemberPrintingConfig.cs +++ b/ObjectPrinting/IMemberPrintingConfig.cs @@ -3,10 +3,9 @@ namespace ObjectPrinting; -public interface IMemberPrintingConfig +public interface IMemberPrintingConfig { IPrintingConfig Config { get; } IPrintingConfig With(Func serializer); - IPrintingConfig With(Expression> expression, Func serializer); } \ No newline at end of file diff --git a/ObjectPrinting/MemberPrintingConfig.cs b/ObjectPrinting/MemberPrintingConfig.cs index 9132d1a3..890bb0a9 100644 --- a/ObjectPrinting/MemberPrintingConfig.cs +++ b/ObjectPrinting/MemberPrintingConfig.cs @@ -1,27 +1,31 @@ using System; using System.Linq.Expressions; +using System.Reflection; namespace ObjectPrinting; public class MemberPrintingConfig : IMemberPrintingConfig { private readonly PrintingConfig config; + private readonly MemberInfo? info; public MemberPrintingConfig(PrintingConfig printingConfig) { config = printingConfig; } - public IPrintingConfig Config => config; - - public IPrintingConfig With(Func serializer) + public MemberPrintingConfig(PrintingConfig printingConfig, MemberInfo info) { - config.AlternativeSerializationForType.Add(typeof(TFieldType), o => serializer((TFieldType)o)); - return config; + config = printingConfig; + this.info = info; } - public IPrintingConfig With(Expression> expression, Func serializer) + public IPrintingConfig Config => config; + + public IPrintingConfig With(Func serializer) { - config.AlternativeSerializationForProp.Add(PrintingConfig.GetPropDetails(expression), o => serializer((TFieldType)o)); + if (info != null) + config.AlternativeSerializationForProp.Add(info, o => serializer((TFieldType)o)); + else config.AlternativeSerializationForType.Add(typeof(TFieldType), o => serializer((TFieldType)o)); return config; } } \ No newline at end of file diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 70fcd4b5..27d2d7e6 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -172,7 +172,7 @@ public IMemberPrintingConfig Serialize() public IMemberPrintingConfig Serialize( Expression> expression) { - return new MemberPrintingConfig(this); + return new MemberPrintingConfig(this, GetPropDetails(expression)); } public IPrintingConfig SetCultureFor(CultureInfo cultureInfo) diff --git a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs index 203d12e1..194f2f55 100644 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs @@ -13,20 +13,19 @@ public void Demo() { var person = new Person { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }; - var printer = ObjectPrinter.For() + var printer = ObjectPrinter.For(); //1. Исключить из сериализации свойства определенного типа - .Exclude() + printer.Exclude(); //2. Указать альтернативный способ сериализации для определенного типа - .Serialize().With(str => str.ToUpper()) + printer.Serialize().With(str => str.ToUpper()); //3. Для числовых типов указать культуру - .SetCultureFor(CultureInfo.InvariantCulture) + printer.SetCultureFor(CultureInfo.InvariantCulture); //4. Настроить сериализацию конкретного свойства - .Serialize(p => p.Name).With(name => name.ToUpper()) + printer.Serialize(p => p.Name).With(name => name.ToUpper()); //5. Настроить обрезание строковых свойств (метод должен быть виден только для строковых свойств) - .TrimString(p => p.Name, 10) + printer.TrimString(p => p.Name, 10); //6. Исключить из сериализации конкретного свойства - .Exclude(p => p.Age) - ; + printer.Exclude(p => p.Age); var s1 = printer.PrintToString(person); Console.WriteLine(s1); From aa27dd593a139734024080a53fe88f70d952d264 Mon Sep 17 00:00:00 2001 From: kexogg Date: Thu, 12 Dec 2024 19:12:01 +0500 Subject: [PATCH 3/6] minor refactoring --- ObjectPrinting/PrintingConfig.cs | 84 +++++++++++++------------------- 1 file changed, 34 insertions(+), 50 deletions(-) diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 27d2d7e6..bd5c7296 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -17,6 +17,7 @@ public class PrintingConfig : IPrintingConfig typeof(bool), typeof(byte), typeof(int), typeof(double), typeof(float), typeof(char), typeof(string), typeof(DateTime), typeof(TimeSpan), typeof(Guid) ]; + private readonly HashSet excludedTypes = new(); private readonly HashSet excludedProps = new(); private readonly HashSet alreadyProcessed = new(ReferenceEqualityComparer.Instance); @@ -51,72 +52,54 @@ private string PrintToString(object? obj, int nestingLevel) return string.Empty; if (alreadyProcessed.Contains(obj)) return "[Recursion]"; - if (TryProcessSimpleType(obj, out var result)) - return result; - if (TryProcessCollection(obj, nestingLevel, out result)) - return result; - if (TryProcessDictionary(obj, nestingLevel, out result)) - return result; - return ProcessNestedObject(obj, nestingLevel); + return obj switch + { + not null when simpleTypes.Contains(obj.GetType()) => ProcessSimpleType(obj), + IDictionary dict => ProcessDictionary(dict, nestingLevel), + IEnumerable list => ProcessCollection(list, nestingLevel), + _ => ProcessNestedObject(obj, nestingLevel) + }; } - private bool TryProcessSimpleType(object obj, out string result) + private string ProcessSimpleType(object obj) { var type = obj.GetType(); - if (simpleTypes.Contains(type)) + var result = (obj switch { - result = (obj switch - { - IFormattable f when currentProp != null && cultureForProp.TryGetValue(currentProp, out var culture) => f.ToString(null, culture), - IFormattable f when cultureForType.ContainsKey(type) => f.ToString(null, cultureForType[type]), - _ => obj.ToString() - })!; + IFormattable f when currentProp != null && cultureForProp.TryGetValue(currentProp, out var culture) => + f.ToString(null, culture), + IFormattable f when cultureForType.ContainsKey(type) => f.ToString(null, cultureForType[type]), + _ => obj.ToString() + })!; - if (currentProp != null && trimLengthForProp.TryGetValue(currentProp, out var length)) - result = result.Length > length ? result[..length] : result; + if (currentProp != null && trimLengthForProp.TryGetValue(currentProp, out var length)) + result = result.Length > length ? result[..length] : result; - return true; - } - - result = string.Empty; - return false; + return result; } - private bool TryProcessCollection(object obj, int nestingLevel, out string result) + private string ProcessCollection(IEnumerable collection, int nestingLevel) { - if (obj is IEnumerable collection) - { - var sb = new StringBuilder(); - foreach (var item in collection) - sb.Append(PrintToString(item, nestingLevel)); - result = sb.ToString(); - return true; - } - - result = string.Empty; - return false; + var sb = new StringBuilder(); + foreach (var item in collection) + sb.Append(PrintToString(item, nestingLevel)); + return sb.ToString(); } - private bool TryProcessDictionary(object obj, int nestingLevel, out string result) + private string ProcessDictionary(IDictionary dictionary, int nestingLevel) { - if (obj is IDictionary dictionary) + var sb = new StringBuilder(); + sb.Append('\t', nestingLevel); + sb.AppendLine(dictionary.GetType().Name); + foreach (DictionaryEntry entry in dictionary) { - var sb = new StringBuilder(); - sb.Append('\t', nestingLevel); - sb.AppendLine(obj.GetType().Name); - foreach (DictionaryEntry entry in dictionary) - { - var key = entry.Key; - var value = entry.Value; - sb.Append('\t', nestingLevel + 1); - sb.AppendLine($"{key.PrintToString()} = {value.PrintToString()}"); - } - result = sb.ToString(); - return true; + var key = entry.Key; + var value = entry.Value; + sb.Append('\t', nestingLevel + 1); + sb.AppendLine($"{key.PrintToString()} = {value.PrintToString()}"); } - result = string.Empty; - return false; + return sb.ToString(); } private string ProcessNestedObject(object obj, int nestingLevel) @@ -135,6 +118,7 @@ private string ProcessNestedObject(object obj, int nestingLevel) sb.Append('\t', nestingLevel + 1); sb.AppendLine($"{property.Name} = {serializedValue}"); } + currentProp = null; return sb.ToString(); From 6fac4a28d4726b1b9f64103c693c3b582472fa5e Mon Sep 17 00:00:00 2001 From: kexogg Date: Thu, 12 Dec 2024 23:37:09 +0500 Subject: [PATCH 4/6] fields fix --- ObjectPrinting/ObjectPrinting.csproj | 6 -- ObjectPrinting/PrintingConfig.cs | 39 ++++++-- 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 --- ..._WithAlternativeSerialization_ForField.txt | 6 ++ ..._WithAlternativeSerialization_ForType.txt} | 0 ...lizeObject_WithCultureSet_ForProperty.txt} | 0 ...erializeObject_WithCultureSet_ForType.txt} | 0 ...ould_SerializeObject_WithExcludedField.txt | 5 + ObjectPrintingTests/Models/Person.cs | 2 +- .../ObjectPrinterAcceptanceTests.cs | 4 +- ObjectPrintingTests/ObjectPrinterTests.cs | 95 ++++++++++++++----- 17 files changed, 116 insertions(+), 225 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 create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForField.txt rename ObjectPrintingTests/ExpectedResults/{ObjectPrinter_Should_SerializeObject_WithAlternativeSerializationForType.txt => ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForType.txt} (100%) rename ObjectPrintingTests/ExpectedResults/{ObjectPrinter_Should_SerializeObject_WithCultureSetForProp.txt => ObjectPrinter_Should_SerializeObject_WithCultureSet_ForProperty.txt} (100%) rename ObjectPrintingTests/ExpectedResults/{ObjectPrinter_Should_SerializeObject_WithCultureSetForType.txt => ObjectPrinter_Should_SerializeObject_WithCultureSet_ForType.txt} (100%) create mode 100644 ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedField.txt rename {ObjectPrinting/Tests => ObjectPrintingTests}/ObjectPrinterAcceptanceTests.cs (96%) diff --git a/ObjectPrinting/ObjectPrinting.csproj b/ObjectPrinting/ObjectPrinting.csproj index aa9b2915..3c4d56b1 100644 --- a/ObjectPrinting/ObjectPrinting.csproj +++ b/ObjectPrinting/ObjectPrinting.csproj @@ -3,10 +3,4 @@ net9.0 enable - - - - - - diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index bd5c7296..05b1b171 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -24,7 +24,7 @@ public class PrintingConfig : IPrintingConfig private readonly Dictionary cultureForType = new(); private readonly Dictionary cultureForProp = new(); private readonly Dictionary trimLengthForProp = new(); - private PropertyInfo? currentProp; + private MemberInfo? currentProp; protected internal readonly Dictionary> AlternativeSerializationForProp = new(); @@ -36,7 +36,7 @@ public string PrintToString(TOwner obj) return PrintToString(obj, 0); } - protected internal static MemberInfo GetPropDetails(Expression> expression) + private static MemberInfo GetPropDetails(Expression> expression) { return expression.Body switch { @@ -91,10 +91,9 @@ private string ProcessDictionary(IDictionary dictionary, int nestingLevel) var sb = new StringBuilder(); sb.Append('\t', nestingLevel); sb.AppendLine(dictionary.GetType().Name); - foreach (DictionaryEntry entry in dictionary) + foreach (var key in dictionary.Keys) { - var key = entry.Key; - var value = entry.Value; + var value = dictionary[key]; sb.Append('\t', nestingLevel + 1); sb.AppendLine($"{key.PrintToString()} = {value.PrintToString()}"); } @@ -119,19 +118,43 @@ private string ProcessNestedObject(object obj, int nestingLevel) sb.AppendLine($"{property.Name} = {serializedValue}"); } + foreach (var field in type.GetFields()) + { + currentProp = field; + if (excludedTypes.Contains(field.FieldType) || excludedProps.Contains(field)) + continue; + var serializedValue = Serialize(field, obj, nestingLevel + 1); + sb.Append('\t', nestingLevel + 1); + sb.AppendLine($"{field.Name} = {serializedValue}"); + } + currentProp = null; return sb.ToString(); } - private string Serialize(PropertyInfo property, object parent, int nestingLevel) + private string Serialize(MemberInfo property, object parent, int nestingLevel) { - var value = property.GetValue(parent); + object value; + Type type; + switch (property) + { + case PropertyInfo prop: + value = prop.GetValue(parent); + type = prop.PropertyType; + break; + case FieldInfo field: + value = field.GetValue(parent); + type = field.FieldType; + break; + default: + return string.Empty; + } if (value == null) return "null"; if (AlternativeSerializationForProp.TryGetValue(property, out var propertySerializer)) return propertySerializer(value); - if (AlternativeSerializationForType.TryGetValue(property.PropertyType, out var typeSerializer)) + if (AlternativeSerializationForType.TryGetValue(type, out var typeSerializer)) return typeSerializer(value); return PrintToString(value, nestingLevel); } 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 diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForField.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForField.txt new file mode 100644 index 00000000..82971729 --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForField.txt @@ -0,0 +1,6 @@ +SkilledPerson + Id = 00000000-0000-0000-0000-000000000000 + Name = Alex + Height = 180 + Age = 19 + Skill = CSHARP diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerializationForType.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForType.txt similarity index 100% rename from ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerializationForType.txt rename to ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForType.txt diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSetForProp.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSet_ForProperty.txt similarity index 100% rename from ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSetForProp.txt rename to ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSet_ForProperty.txt diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSetForType.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSet_ForType.txt similarity index 100% rename from ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSetForType.txt rename to ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithCultureSet_ForType.txt diff --git a/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedField.txt b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedField.txt new file mode 100644 index 00000000..c2149720 --- /dev/null +++ b/ObjectPrintingTests/ExpectedResults/ObjectPrinter_Should_SerializeObject_WithExcludedField.txt @@ -0,0 +1,5 @@ +SkilledPerson + Id = 00000000-0000-0000-0000-000000000000 + Name = Alex + Height = 180 + Age = 19 diff --git a/ObjectPrintingTests/Models/Person.cs b/ObjectPrintingTests/Models/Person.cs index ebe0d74b..0d293fc4 100644 --- a/ObjectPrintingTests/Models/Person.cs +++ b/ObjectPrintingTests/Models/Person.cs @@ -15,6 +15,6 @@ public class Child : Person public class SkilledPerson : Person { - public Dictionary Skills { get; set; } + public string Skill; } } \ No newline at end of file diff --git a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrintingTests/ObjectPrinterAcceptanceTests.cs similarity index 96% rename from ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs rename to ObjectPrintingTests/ObjectPrinterAcceptanceTests.cs index 194f2f55..3c389546 100644 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ b/ObjectPrintingTests/ObjectPrinterAcceptanceTests.cs @@ -1,6 +1,4 @@ -using System; -using System.Globalization; -using NUnit.Framework; +using System.Globalization; using ObjectPrinting.Extensions; namespace ObjectPrinting.Tests diff --git a/ObjectPrintingTests/ObjectPrinterTests.cs b/ObjectPrintingTests/ObjectPrinterTests.cs index ac01a899..0a82ded2 100644 --- a/ObjectPrintingTests/ObjectPrinterTests.cs +++ b/ObjectPrintingTests/ObjectPrinterTests.cs @@ -5,77 +5,98 @@ namespace ObjectPrintingTests; +[Parallelizable(ParallelScope.All)] public class ObjectPrinterTests { - private string expectedString; - [SetUp] - public void Setup() - { - expectedString = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); - } - [Test] public void ObjectPrinter_Should_SerializeObject() { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + var person = new Person { Name = "Alex", Age = 19, Height = 180.5, Id = new Guid() }; var printer = ObjectPrinter.For(); printer.PrintToString(person).Should() - .Be(expectedString); + .Be(expected); } [Test] - public void ObjectPrinter_Should_SerializeObject_WithCultureSetForProp() + public void ObjectPrinter_Should_SerializeObject_WithCultureSet_ForProperty() { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + var person = new Person { Name = "Alex", Age = 19, Height = 180.5, Id = new Guid() }; var printer = ObjectPrinter.For() .SetCultureFor(p => p.Height, CultureInfo.GetCultureInfo("ru-RU")); printer.PrintToString(person).Should() - .Be(expectedString); + .Be(expected); } [Test] - public void ObjectPrinter_Should_SerializeObject_WithCultureSetForType() + public void ObjectPrinter_Should_SerializeObject_WithCultureSet_ForType() { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + var person = new Person { Name = "Alex", Age = 19, Height = 180.5, Id = new Guid() }; var printer = ObjectPrinter.For() .SetCultureFor(CultureInfo.GetCultureInfo("ru-RU")); printer.PrintToString(person).Should() - .Be(expectedString); + .Be(expected); } + [Test] public void ObjectPrinter_Should_SerializeObject_WithTrim() { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + var person = new Person { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }; var printer = ObjectPrinter.For() .TrimString(p => p.Name, 2); printer.PrintToString(person).Should() - .Be(expectedString); + .Be(expected); } [Test] public void ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForProperty() { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + var person = new Person { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }; var printer = ObjectPrinter.For() .Serialize(p => p.Name).With(name => name.ToUpper()); printer.PrintToString(person).Should() - .Be(expectedString); + .Be(expected); + } + + [Test] + public void ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForField() + { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + + var person = new SkilledPerson() { Name = "Alex", Age = 19, Height = 180, Id = new Guid(), Skill = "csharp" }; + + var printer = ObjectPrinter.For() + .Serialize(p => p.Skill).With(skill => skill.ToUpper()); + + printer.PrintToString(person).Should() + .Be(expected); } [Test] - public void ObjectPrinter_Should_SerializeObject_WithAlternativeSerializationForType() + public void ObjectPrinter_Should_SerializeObject_WithAlternativeSerialization_ForType() { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + var person = new Person { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }; var printer = ObjectPrinter.For() @@ -83,36 +104,42 @@ public void ObjectPrinter_Should_SerializeObject_WithAlternativeSerializationFor ; printer.PrintToString(person).Should() - .Be(expectedString); + .Be(expected); } [Test] public void ObjectPrinter_Should_SerializeObject_WithExcludedType() { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + var person = new Person { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }; var printer = ObjectPrinter.For() .Exclude(); printer.PrintToString(person).Should() - .Be(expectedString); + .Be(expected); } [Test] public void ObjectPrinter_Should_SerializeObject_WithExcludedProperty() { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + var person = new Person { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }; var printer = ObjectPrinter.For() .Exclude(p => p.Name); printer.PrintToString(person).Should() - .Be(expectedString); + .Be(expected); } [Test] public void ObjectPrinter_Should_SerializeObject_WithExcludedNestedProperty() { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + var person = new Child() { Name = "Alex", Age = 19, Height = 180, Id = new Guid(), @@ -121,12 +148,14 @@ public void ObjectPrinter_Should_SerializeObject_WithExcludedNestedProperty() var printer = ObjectPrinter.For() .Exclude(p => p.Parent.Name); printer.PrintToString(person).Should() - .Be(expectedString); + .Be(expected); } [Test] public void ObjectPrinter_Should_SerializeCollection() { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + var persons = new List { new() { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }, @@ -137,11 +166,14 @@ public void ObjectPrinter_Should_SerializeCollection() printer.PrintToString(persons).Should() .Be( - expectedString); + expected); } + [Test] public void ObjectPrinter_Should_SerializeDictionary() { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + var dictionary = new Dictionary { { "one", 1 }, @@ -149,12 +181,14 @@ public void ObjectPrinter_Should_SerializeDictionary() }; var printer = ObjectPrinter.For>(); printer.PrintToString(dictionary).Should() - .Be(expectedString); + .Be(expected); } [Test] public void ObjectPrinter_Should_HandleRecursion() { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + var child = new Child() { Name = "Alex", Age = 19, Height = 180, Id = new Guid(), @@ -162,12 +196,14 @@ public void ObjectPrinter_Should_HandleRecursion() child.Parent = child; var printer = ObjectPrinter.For(); printer.PrintToString(child).Should() - .Be(expectedString); + .Be(expected); } [Test] public void ObjectPrinter_Should_SerializeArray() { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + var people = new Person[] { new() { Name = "Alex", Age = 19, Height = 180, Id = new Guid() }, @@ -175,7 +211,20 @@ public void ObjectPrinter_Should_SerializeArray() }; var printer = ObjectPrinter.For(); printer.PrintToString(people).Should() - .Be(expectedString); + .Be(expected); } + [Test] + public void ObjectPrinter_Should_SerializeObject_WithExcludedField() + { + var expected = File.ReadAllText($"ExpectedResults/{TestContext.CurrentContext.Test.MethodName}.txt"); + + var person = new SkilledPerson + { + Name = "Alex", Age = 19, Height = 180, Id = new Guid(), Skill = "C#" + }; + var printer = ObjectPrinter.For() + .Exclude(p => p.Skill); + printer.PrintToString(person).Should().Be(expected); + } } \ No newline at end of file From 06da56c0d73e47d8ebb870692f96ca0d74dc63a6 Mon Sep 17 00:00:00 2001 From: kexogg Date: Thu, 12 Dec 2024 23:45:08 +0500 Subject: [PATCH 5/6] remove currentProp field --- ObjectPrinting/PrintingConfig.cs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 05b1b171..a1b2efc7 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -24,7 +24,6 @@ public class PrintingConfig : IPrintingConfig private readonly Dictionary cultureForType = new(); private readonly Dictionary cultureForProp = new(); private readonly Dictionary trimLengthForProp = new(); - private MemberInfo? currentProp; protected internal readonly Dictionary> AlternativeSerializationForProp = new(); @@ -46,7 +45,7 @@ private static MemberInfo GetPropDetails(Expression> expressi }; } - private string PrintToString(object? obj, int nestingLevel) + private string PrintToString(object? obj, int nestingLevel, MemberInfo? memberInfo = null) { if (obj == null) return string.Empty; @@ -54,25 +53,25 @@ private string PrintToString(object? obj, int nestingLevel) return "[Recursion]"; return obj switch { - not null when simpleTypes.Contains(obj.GetType()) => ProcessSimpleType(obj), + not null when simpleTypes.Contains(obj.GetType()) => ProcessSimpleType(obj, memberInfo), IDictionary dict => ProcessDictionary(dict, nestingLevel), IEnumerable list => ProcessCollection(list, nestingLevel), _ => ProcessNestedObject(obj, nestingLevel) }; } - private string ProcessSimpleType(object obj) + private string ProcessSimpleType(object obj, MemberInfo? memeberInfo = null) { var type = obj.GetType(); var result = (obj switch { - IFormattable f when currentProp != null && cultureForProp.TryGetValue(currentProp, out var culture) => + IFormattable f when memeberInfo != null && cultureForProp.TryGetValue(memeberInfo, out var culture) => f.ToString(null, culture), IFormattable f when cultureForType.ContainsKey(type) => f.ToString(null, cultureForType[type]), _ => obj.ToString() })!; - if (currentProp != null && trimLengthForProp.TryGetValue(currentProp, out var length)) + if (memeberInfo != null && trimLengthForProp.TryGetValue(memeberInfo, out var length)) result = result.Length > length ? result[..length] : result; return result; @@ -110,7 +109,6 @@ private string ProcessNestedObject(object obj, int nestingLevel) foreach (var property in type.GetProperties()) { - currentProp = property; if (excludedTypes.Contains(property.PropertyType) || excludedProps.Contains(property)) continue; var serializedValue = Serialize(property, obj, nestingLevel + 1); @@ -120,7 +118,6 @@ private string ProcessNestedObject(object obj, int nestingLevel) foreach (var field in type.GetFields()) { - currentProp = field; if (excludedTypes.Contains(field.FieldType) || excludedProps.Contains(field)) continue; var serializedValue = Serialize(field, obj, nestingLevel + 1); @@ -128,16 +125,14 @@ private string ProcessNestedObject(object obj, int nestingLevel) sb.AppendLine($"{field.Name} = {serializedValue}"); } - currentProp = null; - return sb.ToString(); } - private string Serialize(MemberInfo property, object parent, int nestingLevel) + private string Serialize(MemberInfo memberInfo, object parent, int nestingLevel) { object value; Type type; - switch (property) + switch (memberInfo) { case PropertyInfo prop: value = prop.GetValue(parent); @@ -152,11 +147,11 @@ private string Serialize(MemberInfo property, object parent, int nestingLevel) } if (value == null) return "null"; - if (AlternativeSerializationForProp.TryGetValue(property, out var propertySerializer)) + if (AlternativeSerializationForProp.TryGetValue(memberInfo, out var propertySerializer)) return propertySerializer(value); if (AlternativeSerializationForType.TryGetValue(type, out var typeSerializer)) return typeSerializer(value); - return PrintToString(value, nestingLevel); + return PrintToString(value, nestingLevel, memberInfo); } public IPrintingConfig Exclude() From eaf1a652d9cbd675491dab14567c17830c9c8001 Mon Sep 17 00:00:00 2001 From: kexogg Date: Thu, 12 Dec 2024 23:59:45 +0500 Subject: [PATCH 6/6] type fixes --- ObjectPrinting/IPrintingConifg.cs | 2 +- ObjectPrinting/PrintingConfig.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ObjectPrinting/IPrintingConifg.cs b/ObjectPrinting/IPrintingConifg.cs index 0cedd895..b07a0b45 100644 --- a/ObjectPrinting/IPrintingConifg.cs +++ b/ObjectPrinting/IPrintingConifg.cs @@ -9,7 +9,7 @@ public interface IPrintingConfig IPrintingConfig Exclude(); IPrintingConfig Exclude(Expression> expression); IMemberPrintingConfig Serialize(); - IMemberPrintingConfig Serialize(Expression> expression); + IMemberPrintingConfig Serialize(Expression> expression); IPrintingConfig SetCultureFor(CultureInfo cultureInfo); IPrintingConfig SetCultureFor(Expression> expression, CultureInfo cultureInfo); IPrintingConfig TrimString(Expression> expression, int length); diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index a1b2efc7..19498539 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -172,7 +172,7 @@ public IMemberPrintingConfig Serialize() } public IMemberPrintingConfig Serialize( - Expression> expression) + Expression> expression) { return new MemberPrintingConfig(this, GetPropDetails(expression)); }