From 948ccb9d920fcea50f5d3656abeea6f9f9986a4f Mon Sep 17 00:00:00 2001 From: caiman Date: Tue, 26 Dec 2023 02:06:45 +0500 Subject: [PATCH 1/6] first realization --- .../Extensions/DictionaryExtensions.cs | 41 ++++ .../Extensions/EnumerableExtensions.cs | 67 +++++++ ObjectPrinting/Extensions/ObjectExtensions.cs | 14 ++ ObjectPrinting/ISerializer.cs | 11 ++ ObjectPrinting/ISerializerSetter.cs | 10 + ObjectPrinting/ObjectPrinting.csproj | 2 +- ObjectPrinting/PrintingConfig.cs | 178 +++++++++++++++--- ObjectPrinting/Serializer.cs | 30 +++ .../Tests/ObjectPrinterAcceptanceTests.cs | 46 ++++- ObjectPrinting/Tests/Person.cs | 2 + 10 files changed, 365 insertions(+), 36 deletions(-) create mode 100644 ObjectPrinting/Extensions/DictionaryExtensions.cs create mode 100644 ObjectPrinting/Extensions/EnumerableExtensions.cs create mode 100644 ObjectPrinting/Extensions/ObjectExtensions.cs create mode 100644 ObjectPrinting/ISerializer.cs create mode 100644 ObjectPrinting/ISerializerSetter.cs create mode 100644 ObjectPrinting/Serializer.cs diff --git a/ObjectPrinting/Extensions/DictionaryExtensions.cs b/ObjectPrinting/Extensions/DictionaryExtensions.cs new file mode 100644 index 00000000..1c37a992 --- /dev/null +++ b/ObjectPrinting/Extensions/DictionaryExtensions.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +namespace ObjectPrinting.Extensions; + +public static class DictionaryExtensions +{ + public static string ObjectPrintDictionary( + this IDictionary dictionary, + PrintingConfig printingConfig, + ImmutableList previous) + { + // var sb = new StringBuilder("{"); + // sb.Append(Environment.NewLine); + // + // var identation = new string('\t', previous.Count); + // previous = previous.Add(dictionary); + // + // foreach (var (key, value) in dictionary) + // { + // sb.Append(identation); + // sb.Append(key); + // sb.Append(": "); + // sb.Append(printingConfig.PrintToString1(value, previous)); + // sb.Append(','); + // sb.Append(Environment.NewLine); + // } + // + // sb.Append(new string('\t', previous.Count - 1)); + // sb.Append('}'); + // + // return sb.ToString(); + previous = previous.Add(dictionary); + + return dictionary.AsEnumerable().EnumerateForObjectPrinting( + "{", "}", + pair => $"{pair.Key}: {printingConfig.PrintToString1(pair.Value, previous)}", + previous); + } +} \ No newline at end of file diff --git a/ObjectPrinting/Extensions/EnumerableExtensions.cs b/ObjectPrinting/Extensions/EnumerableExtensions.cs new file mode 100644 index 00000000..22da3bf7 --- /dev/null +++ b/ObjectPrinting/Extensions/EnumerableExtensions.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; + +namespace ObjectPrinting.Extensions; + +public static class EnumerableExtensions +{ + public static string ObjectPrintEnumerable( + this IEnumerable enumerable, + PrintingConfig printingConfig, + ImmutableList previous) + { + // var sb = new StringBuilder("["); + // sb.Append(Environment.NewLine); + // + // var identation = new string('\t', previous.Count); + // previous = previous.Add(enumerable); + // + // foreach (var obj in enumerable) + // { + // sb.Append(identation); + // sb.Append(printingConfig.PrintToString1(obj, previous)); + // sb.Append(','); + // sb.Append(Environment.NewLine); + // } + // + // sb.Append(new string('\t', previous.Count - 1)); + // sb.Append(']'); + // + // return sb.ToString(); + + previous = previous.Add(enumerable); + + return enumerable.EnumerateForObjectPrinting( + "{", "}", + obj => printingConfig.PrintToString1(obj, previous), + previous); + } + + public static string EnumerateForObjectPrinting( + this IEnumerable enumerable, + string startSymbol, + string endSymbol, + Func getStringElement, + ImmutableList previous) + { + var sb = new StringBuilder(); + sb.AppendLine(startSymbol); + + var identation = new string('\t', previous.Count - 1); + + foreach (var obj in enumerable) + { + sb.Append(identation); + sb.Append(getStringElement(obj)); + sb.AppendLine(","); + } + + sb.Append(new string('\t', previous.Count - 1)); + sb.AppendLine(endSymbol); + + return sb.ToString(); + } +} \ No newline at end of file diff --git a/ObjectPrinting/Extensions/ObjectExtensions.cs b/ObjectPrinting/Extensions/ObjectExtensions.cs new file mode 100644 index 00000000..edce1821 --- /dev/null +++ b/ObjectPrinting/Extensions/ObjectExtensions.cs @@ -0,0 +1,14 @@ +namespace ObjectPrinting.Extensions; + +public static class ObjectExtensions +{ + public static string PrintToString(this T obj) + { + return ObjectPrinter.For().PrintToString(obj); + } + + public static string PrintToString(this T obj, PrintingConfig printingConfig) + { + return printingConfig.PrintToString(obj); + } +} \ No newline at end of file diff --git a/ObjectPrinting/ISerializer.cs b/ObjectPrinting/ISerializer.cs new file mode 100644 index 00000000..4fb93d61 --- /dev/null +++ b/ObjectPrinting/ISerializer.cs @@ -0,0 +1,11 @@ +using System; +using System.Globalization; + +namespace ObjectPrinting +{ + public interface ISerializer + { + public PrintingConfig PrintingConfig { get; } + public PrintingConfig Serialize(Func serializer); + } +} \ No newline at end of file diff --git a/ObjectPrinting/ISerializerSetter.cs b/ObjectPrinting/ISerializerSetter.cs new file mode 100644 index 00000000..e7b8dab9 --- /dev/null +++ b/ObjectPrinting/ISerializerSetter.cs @@ -0,0 +1,10 @@ +using System; +using System.Reflection; + +namespace ObjectPrinting +{ + public interface ISerializerSetter + { + public void SetSerializer(Func serializer, PropertyInfo propertyInfo); + } +} \ No newline at end of file diff --git a/ObjectPrinting/ObjectPrinting.csproj b/ObjectPrinting/ObjectPrinting.csproj index 1c5eaf1c..fb67b65b 100644 --- a/ObjectPrinting/ObjectPrinting.csproj +++ b/ObjectPrinting/ObjectPrinting.csproj @@ -1,7 +1,7 @@  - 8 + latest netcoreapp3.1 false diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index a9e08211..f5382d68 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -1,41 +1,159 @@ using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Globalization; using System.Linq; +using System.Linq.Expressions; +using System.Reflection; using System.Text; +using ObjectPrinting.Extensions; -namespace ObjectPrinting +namespace ObjectPrinting; + +public class PrintingConfig : ISerializerSetter { - public class PrintingConfig + private readonly Dictionary> typeSerializers = new(); + private readonly Dictionary> propertySerializers = new(); + + private readonly HashSet excludedProps = new(); + private readonly HashSet excludedTypes = new(); + + static PrintingConfig() { - public string PrintToString(TOwner obj) - { - return PrintToString(obj, 0); - } + } + + public PrintingConfig Exclude() + { + excludedTypes.Add(typeof(T)); + return this; + } + + public PrintingConfig Exclude(Expression> expression) + { + if (expression.Body is not MemberExpression memberExpression) + throw new ArgumentException($"Expression {expression} is not MemberExpression"); + + var propertyInfo = memberExpression.Member as PropertyInfo; + excludedProps.Add(propertyInfo); + + return this; + } + + public ISerializer Select() + { + return new Serializer(this); + } + + public ISerializer Select(Expression> memberExpression) + { + var propertyInfo = (memberExpression.Body as MemberExpression).Member as PropertyInfo; + return new Serializer(this, propertyInfo); + } + + public PrintingConfig SetCulture(CultureInfo cultureInfo) + where T: IFormattable + { + return Select() + .Serialize(obj => string.Format(cultureInfo, "{0}", obj)); + } + + public PrintingConfig SliceStrings(int maxLength) + { + if (maxLength <= 0) + throw new ArgumentException("Parameter maxLength must be positive"); + + return Select() + .Serialize(s => s[..maxLength]); + } + + void ISerializerSetter.SetSerializer(Func serializer, PropertyInfo propertyInfo) + { + if (propertyInfo is not null) + propertySerializers[propertyInfo] = obj => serializer((T) obj); + else + typeSerializers[typeof(T)] = obj => serializer((T) obj); + } + + public string PrintToString(TOwner obj) + { + return PrintToString1(obj, new List().ToImmutableList()); + } + + public string PrintToString1(object obj, ImmutableList previous) + { + if (obj == null) + return "null" + Environment.NewLine; - private string PrintToString(object obj, int nestingLevel) + var type = obj.GetType(); + + if (TrySerializeValueType(type, obj, out var serializedValue)) + return serializedValue; + + if (IsCyclic(obj, previous)) + return "cyclic link"; + + if (obj is IDictionary dictionary) + return dictionary.ObjectPrintDictionary(this, previous); + + if (obj is IEnumerable enumerable) + return enumerable.ObjectPrintEnumerable(this, previous); + + var identation = new string('\t', previous.Count + 1); + previous = previous.Add(obj); + var sb = new StringBuilder(); + sb.AppendLine(type.Name); + + foreach (var property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { - //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(); + if (IsExcluded(property)) + continue; + + sb.Append($"{identation}{property.Name}: "); + + if (TrySerializeProperty(obj, property, out var serialized)) + sb.Append(serialized); + else + sb.Append(PrintToString1(property.GetValue(obj), previous)); + + sb.AppendLine(","); } + + return sb.ToString(); + } + + private bool TrySerializeValueType(Type type, object obj, out string serialized) + { + serialized = ""; + + if (obj is not string && !type.IsValueType) + return false; + + serialized = typeSerializers.TryGetValue(type, out var serializer) + ? serializer(obj) + : obj.ToString(); + + return true; + } + + private bool IsCyclic(object current, IEnumerable previous) + { + return previous.Any(e => ReferenceEquals(e, current)); + } + + private bool IsExcluded(PropertyInfo propertyInfo) + { + return excludedProps.Contains(propertyInfo) || excludedTypes.Contains(propertyInfo.PropertyType); + } + + private bool TrySerializeProperty(object obj, PropertyInfo propertyInfo, out string serialized) + { + serialized = ""; + + if (!propertySerializers.TryGetValue(propertyInfo, out var serializer)) + return false; + + serialized = serializer(propertyInfo.GetValue(obj)); + return true; } } \ No newline at end of file diff --git a/ObjectPrinting/Serializer.cs b/ObjectPrinting/Serializer.cs new file mode 100644 index 00000000..73df01fe --- /dev/null +++ b/ObjectPrinting/Serializer.cs @@ -0,0 +1,30 @@ +using System; +using System.Globalization; +using System.Reflection; + +namespace ObjectPrinting +{ + public class Serializer : ISerializer + { + public PrintingConfig PrintingConfig { get; } + private readonly PropertyInfo propertyInfo; + + public Serializer(PrintingConfig printingConfig, PropertyInfo propertyInfo) + { + PrintingConfig = printingConfig; + this.propertyInfo = propertyInfo; + } + + public Serializer(PrintingConfig printingConfig) + { + PrintingConfig = printingConfig; + } + + public PrintingConfig Serialize(Func serializer) + { + (PrintingConfig as ISerializerSetter).SetSerializer(serializer, propertyInfo); + + return PrintingConfig; + } + } +} \ No newline at end of file diff --git a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs index 4c8b2445..a3bb3d5b 100644 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs @@ -1,27 +1,63 @@ -using NUnit.Framework; +using System; +using System.Globalization; +using NUnit.Framework; namespace ObjectPrinting.Tests { [TestFixture] public class ObjectPrinterAcceptanceTests { + private Person _person; + private PrintingConfig _printer; + + [SetUp] + public void SetUp() + { + _person = new Person + { + Name = "Frank", + Surname = "Sinatra", + Age = 19000000, + Id = new Guid(), + Height = 180.5, + Money = 300, + }; + + _printer = ObjectPrinter.For(); + } + [Test] public void Demo() { - var person = new Person { Name = "Alex", Age = 19 }; - - var printer = ObjectPrinter.For(); //1. Исключить из сериализации свойства определенного типа //2. Указать альтернативный способ сериализации для определенного типа //3. Для числовых типов указать культуру //4. Настроить сериализацию конкретного свойства //5. Настроить обрезание строковых свойств (метод должен быть виден только для строковых свойств) //6. Исключить из сериализации конкретного свойства + + _printer + .Exclude() + .Exclude(p => p.Id); - string s1 = printer.PrintToString(person); + Console.WriteLine(_printer.PrintToString(_person)); //7. Синтаксический сахар в виде метода расширения, сериализующего по-умолчанию //8. ...с конфигурированием } + + [Test] + public void Exclude_ShouldExcludeGivenProperty() + { + _printer + .Exclude() + .Exclude(p => p.Id) + .Select().Serialize(n => Math.Round(n).ToString()) + // .Select(x => x.Name).Serialize(s => s.ToLower()) + .SetCulture(CultureInfo.CurrentCulture) + .SliceStrings(2); + + Console.WriteLine(_printer.PrintToString(_person)); + } } } \ No newline at end of file diff --git a/ObjectPrinting/Tests/Person.cs b/ObjectPrinting/Tests/Person.cs index f9555955..b939e1bc 100644 --- a/ObjectPrinting/Tests/Person.cs +++ b/ObjectPrinting/Tests/Person.cs @@ -6,7 +6,9 @@ public class Person { public Guid Id { get; set; } public string Name { get; set; } + public string Surname { get; set; } public double Height { get; set; } public int Age { get; set; } + public long Money { get; set; } } } \ No newline at end of file From 0264935f1bc475066e194f41d24905c388ea5470 Mon Sep 17 00:00:00 2001 From: caiman Date: Tue, 26 Dec 2023 16:08:56 +0500 Subject: [PATCH 2/6] tests + fixing bugs --- .../Extensions/DictionaryExtensions.cs | 41 ---- .../Extensions/EnumerableExtensions.cs | 31 +-- .../Extensions/IDictionaryExtensions.cs | 29 +++ ObjectPrinting/ObjectPrinting.csproj | 5 - ObjectPrinting/PrintingConfig.cs | 49 ++-- ObjectPrinting/Serializer.cs | 1 - 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 - .../Tests/ObjectPrinterAcceptanceTests.cs | 63 ----- ObjectPrinting/Tests/Person.cs | 14 -- ObjectPrintingTests/ObjectPrintingTests.cs | 223 ++++++++++++++++++ .../ObjectPrintingTests.csproj | 25 ++ ObjectPrintingTests/Objects/CultureObject.cs | 7 + ObjectPrintingTests/Objects/CyclicObject.cs | 7 + ObjectPrintingTests/Objects/FullName.cs | 7 + ObjectPrintingTests/Objects/Person.cs | 11 + ObjectPrintingTests/Objects/Room.cs | 8 + ObjectPrintingTests/Usings.cs | 4 + fluent-api.sln | 6 + 24 files changed, 361 insertions(+), 354 deletions(-) delete mode 100644 ObjectPrinting/Extensions/DictionaryExtensions.cs create mode 100644 ObjectPrinting/Extensions/IDictionaryExtensions.cs 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 delete mode 100644 ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs delete mode 100644 ObjectPrinting/Tests/Person.cs create mode 100644 ObjectPrintingTests/ObjectPrintingTests.cs create mode 100644 ObjectPrintingTests/ObjectPrintingTests.csproj create mode 100644 ObjectPrintingTests/Objects/CultureObject.cs create mode 100644 ObjectPrintingTests/Objects/CyclicObject.cs create mode 100644 ObjectPrintingTests/Objects/FullName.cs create mode 100644 ObjectPrintingTests/Objects/Person.cs create mode 100644 ObjectPrintingTests/Objects/Room.cs create mode 100644 ObjectPrintingTests/Usings.cs diff --git a/ObjectPrinting/Extensions/DictionaryExtensions.cs b/ObjectPrinting/Extensions/DictionaryExtensions.cs deleted file mode 100644 index 1c37a992..00000000 --- a/ObjectPrinting/Extensions/DictionaryExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; - -namespace ObjectPrinting.Extensions; - -public static class DictionaryExtensions -{ - public static string ObjectPrintDictionary( - this IDictionary dictionary, - PrintingConfig printingConfig, - ImmutableList previous) - { - // var sb = new StringBuilder("{"); - // sb.Append(Environment.NewLine); - // - // var identation = new string('\t', previous.Count); - // previous = previous.Add(dictionary); - // - // foreach (var (key, value) in dictionary) - // { - // sb.Append(identation); - // sb.Append(key); - // sb.Append(": "); - // sb.Append(printingConfig.PrintToString1(value, previous)); - // sb.Append(','); - // sb.Append(Environment.NewLine); - // } - // - // sb.Append(new string('\t', previous.Count - 1)); - // sb.Append('}'); - // - // return sb.ToString(); - previous = previous.Add(dictionary); - - return dictionary.AsEnumerable().EnumerateForObjectPrinting( - "{", "}", - pair => $"{pair.Key}: {printingConfig.PrintToString1(pair.Value, previous)}", - previous); - } -} \ No newline at end of file diff --git a/ObjectPrinting/Extensions/EnumerableExtensions.cs b/ObjectPrinting/Extensions/EnumerableExtensions.cs index 22da3bf7..956558c8 100644 --- a/ObjectPrinting/Extensions/EnumerableExtensions.cs +++ b/ObjectPrinting/Extensions/EnumerableExtensions.cs @@ -13,30 +13,12 @@ public static string ObjectPrintEnumerable( PrintingConfig printingConfig, ImmutableList previous) { - // var sb = new StringBuilder("["); - // sb.Append(Environment.NewLine); - // - // var identation = new string('\t', previous.Count); - // previous = previous.Add(enumerable); - // - // foreach (var obj in enumerable) - // { - // sb.Append(identation); - // sb.Append(printingConfig.PrintToString1(obj, previous)); - // sb.Append(','); - // sb.Append(Environment.NewLine); - // } - // - // sb.Append(new string('\t', previous.Count - 1)); - // sb.Append(']'); - // - // return sb.ToString(); previous = previous.Add(enumerable); return enumerable.EnumerateForObjectPrinting( - "{", "}", - obj => printingConfig.PrintToString1(obj, previous), + "[", "]", + obj => $"{printingConfig.PrintToString1(obj, previous)},", previous); } @@ -44,23 +26,22 @@ public static string EnumerateForObjectPrinting( this IEnumerable enumerable, string startSymbol, string endSymbol, - Func getStringElement, + Func getRow, ImmutableList previous) { var sb = new StringBuilder(); sb.AppendLine(startSymbol); - var identation = new string('\t', previous.Count - 1); + var identation = new string('\t', previous.Count); foreach (var obj in enumerable) { sb.Append(identation); - sb.Append(getStringElement(obj)); - sb.AppendLine(","); + sb.AppendLine(getRow(obj)); } sb.Append(new string('\t', previous.Count - 1)); - sb.AppendLine(endSymbol); + sb.Append(endSymbol); return sb.ToString(); } diff --git a/ObjectPrinting/Extensions/IDictionaryExtensions.cs b/ObjectPrinting/Extensions/IDictionaryExtensions.cs new file mode 100644 index 00000000..d6b11633 --- /dev/null +++ b/ObjectPrinting/Extensions/IDictionaryExtensions.cs @@ -0,0 +1,29 @@ +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace ObjectPrinting.Extensions; + +public static class DictionaryExtensions +{ + public static string ObjectPrintDictionary( + this IDictionary dictionary, + PrintingConfig printingConfig, + ImmutableList previous) + { + previous = previous.Add(dictionary); + + return dictionary + .KeysToValues() + .EnumerateForObjectPrinting( + "{", "}", + pair => $"{pair.Key}: {printingConfig.PrintToString1(pair.Value, previous)};", + previous); + } + + private static IEnumerable KeysToValues(this IDictionary dictionary) + { + foreach (DictionaryEntry entry in dictionary) + yield return entry; + } +} \ No newline at end of file diff --git a/ObjectPrinting/ObjectPrinting.csproj b/ObjectPrinting/ObjectPrinting.csproj index fb67b65b..b871c4c9 100644 --- a/ObjectPrinting/ObjectPrinting.csproj +++ b/ObjectPrinting/ObjectPrinting.csproj @@ -6,9 +6,4 @@ false - - - - - diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index f5382d68..3af12c38 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -19,10 +19,6 @@ public class PrintingConfig : ISerializerSetter private readonly HashSet excludedProps = new(); private readonly HashSet excludedTypes = new(); - static PrintingConfig() - { - } - public PrintingConfig Exclude() { excludedTypes.Add(typeof(T)); @@ -31,12 +27,7 @@ public PrintingConfig Exclude() public PrintingConfig Exclude(Expression> expression) { - if (expression.Body is not MemberExpression memberExpression) - throw new ArgumentException($"Expression {expression} is not MemberExpression"); - - var propertyInfo = memberExpression.Member as PropertyInfo; - excludedProps.Add(propertyInfo); - + excludedProps.Add(GetPropertyInfoFromExpression(expression)); return this; } @@ -45,10 +36,9 @@ public ISerializer Select() return new Serializer(this); } - public ISerializer Select(Expression> memberExpression) + public ISerializer Select(Expression> expression) { - var propertyInfo = (memberExpression.Body as MemberExpression).Member as PropertyInfo; - return new Serializer(this, propertyInfo); + return new Serializer(this, GetPropertyInfoFromExpression(expression)); } public PrintingConfig SetCulture(CultureInfo cultureInfo) @@ -58,13 +48,20 @@ public PrintingConfig SetCulture(CultureInfo cultureInfo) .Serialize(obj => string.Format(cultureInfo, "{0}", obj)); } + public PrintingConfig SetCulture(Expression> expression, CultureInfo cultureInfo) + where T: IFormattable + { + return Select(expression) + .Serialize(obj => string.Format(cultureInfo, "{0}", obj)); + } + public PrintingConfig SliceStrings(int maxLength) { if (maxLength <= 0) throw new ArgumentException("Parameter maxLength must be positive"); return Select() - .Serialize(s => s[..maxLength]); + .Serialize(s => maxLength >= s.Length ? s : s[..maxLength]); } void ISerializerSetter.SetSerializer(Func serializer, PropertyInfo propertyInfo) @@ -83,7 +80,7 @@ public string PrintToString(TOwner obj) public string PrintToString1(object obj, ImmutableList previous) { if (obj == null) - return "null" + Environment.NewLine; + return "null"; var type = obj.GetType(); @@ -93,22 +90,22 @@ public string PrintToString1(object obj, ImmutableList previous) if (IsCyclic(obj, previous)) return "cyclic link"; - if (obj is IDictionary dictionary) + if (obj is IDictionary dictionary) return dictionary.ObjectPrintDictionary(this, previous); - if (obj is IEnumerable enumerable) - return enumerable.ObjectPrintEnumerable(this, previous); + if (obj is IEnumerable enumerable) + return enumerable.Cast().ObjectPrintEnumerable(this, previous); var identation = new string('\t', previous.Count + 1); previous = previous.Add(obj); var sb = new StringBuilder(); - sb.AppendLine(type.Name); + sb.AppendLine(type.Name + " ("); foreach (var property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (IsExcluded(property)) continue; - + sb.Append($"{identation}{property.Name}: "); if (TrySerializeProperty(obj, property, out var serialized)) @@ -116,8 +113,10 @@ public string PrintToString1(object obj, ImmutableList previous) else sb.Append(PrintToString1(property.GetValue(obj), previous)); - sb.AppendLine(","); + sb.AppendLine(";"); } + + sb.Append(new string('\t', previous.Count - 1) + ")"); return sb.ToString(); } @@ -156,4 +155,12 @@ private bool TrySerializeProperty(object obj, PropertyInfo propertyInfo, out str serialized = serializer(propertyInfo.GetValue(obj)); return true; } + + private PropertyInfo GetPropertyInfoFromExpression(Expression> expression) + { + if (expression.Body is not MemberExpression memberExpression) + throw new ArgumentException($"Expression {expression} is not MemberExpression"); + + return memberExpression.Member as PropertyInfo; + } } \ No newline at end of file diff --git a/ObjectPrinting/Serializer.cs b/ObjectPrinting/Serializer.cs index 73df01fe..7ee11720 100644 --- a/ObjectPrinting/Serializer.cs +++ b/ObjectPrinting/Serializer.cs @@ -1,5 +1,4 @@ using System; -using System.Globalization; using System.Reflection; namespace ObjectPrinting 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/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs b/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs deleted file mode 100644 index a3bb3d5b..00000000 --- a/ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Globalization; -using NUnit.Framework; - -namespace ObjectPrinting.Tests -{ - [TestFixture] - public class ObjectPrinterAcceptanceTests - { - private Person _person; - private PrintingConfig _printer; - - [SetUp] - public void SetUp() - { - _person = new Person - { - Name = "Frank", - Surname = "Sinatra", - Age = 19000000, - Id = new Guid(), - Height = 180.5, - Money = 300, - }; - - _printer = ObjectPrinter.For(); - } - - [Test] - public void Demo() - { - //1. Исключить из сериализации свойства определенного типа - //2. Указать альтернативный способ сериализации для определенного типа - //3. Для числовых типов указать культуру - //4. Настроить сериализацию конкретного свойства - //5. Настроить обрезание строковых свойств (метод должен быть виден только для строковых свойств) - //6. Исключить из сериализации конкретного свойства - - _printer - .Exclude() - .Exclude(p => p.Id); - - Console.WriteLine(_printer.PrintToString(_person)); - - //7. Синтаксический сахар в виде метода расширения, сериализующего по-умолчанию - //8. ...с конфигурированием - } - - [Test] - public void Exclude_ShouldExcludeGivenProperty() - { - _printer - .Exclude() - .Exclude(p => p.Id) - .Select().Serialize(n => Math.Round(n).ToString()) - // .Select(x => x.Name).Serialize(s => s.ToLower()) - .SetCulture(CultureInfo.CurrentCulture) - .SliceStrings(2); - - Console.WriteLine(_printer.PrintToString(_person)); - } - } -} \ No newline at end of file diff --git a/ObjectPrinting/Tests/Person.cs b/ObjectPrinting/Tests/Person.cs deleted file mode 100644 index b939e1bc..00000000 --- a/ObjectPrinting/Tests/Person.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace ObjectPrinting.Tests -{ - public class Person - { - public Guid Id { get; set; } - public string Name { get; set; } - public string Surname { get; set; } - public double Height { get; set; } - public int Age { get; set; } - public long Money { get; set; } - } -} \ No newline at end of file diff --git a/ObjectPrintingTests/ObjectPrintingTests.cs b/ObjectPrintingTests/ObjectPrintingTests.cs new file mode 100644 index 00000000..4234d6d5 --- /dev/null +++ b/ObjectPrintingTests/ObjectPrintingTests.cs @@ -0,0 +1,223 @@ +using System.Collections; +using System.Globalization; +using ObjectPrinting.Extensions; + +namespace ObjectPrintingTests; + +public class ObjectPrintingTests +{ + private Person person; + private Room room; + + [SetUp] + public void SetUp() + { + person = new Person + { + Name = "Frank", + Surname = "Sinatra", + Age = 19000000, + Id = new Guid(), + Height = 180.5, + Money = 300, + }; + + room = new Room + { + Width = 32.5, + Length = 48.6, + Height = 2.2, + }; + } + + [Test] + public void Exclude_ExcludesGivenTypes() + { + var printer = ObjectPrinter.For() + .Exclude() + .Exclude() + .Exclude(); + + printer.PrintToString(person) + .Should() + .Be("Person (\n\tHeight: 180,5;\n\tAge: 19000000;\n)"); + } + + [Test] + public void Exclude_ExcludesGivenProperties() + { + var printer = ObjectPrinter.For() + .Exclude(p => p.Id) + .Exclude(p => p.Name) + .Exclude(p => p.Height); + + printer.PrintToString(person) + .Should() + .Be("Person (\n\tSurname: Sinatra;\n\tAge: 19000000;\n\tMoney: 300;\n)"); + } + + [Test] + public void Select_SerializesSpecifiedTypes() + { + var printer = ObjectPrinter.For() + .Select().Serialize(num => Math.Ceiling(num).ToString()); + + printer.PrintToString(room) + .Should() + .Be("Room (\n\tWidth: 33;\n\tLength: 49;\n\tHeight: 3;\n)"); + } + + [Test] + public void Select_SerializesSpecifiedProperties() + { + var printer = ObjectPrinter.For() + .Select(r => r.Height).Serialize(num => (num / 2).ToString()); + + printer.PrintToString(room) + .Should() + .Be("Room (\n\tWidth: 32,5;\n\tLength: 48,6;\n\tHeight: 1,1;\n)"); + } + + [Test] + public void SetCulture_WorksWithGivenType() + { + var cultureObject = new CultureObject + { + DateTimeProp = new DateTime(2020, 01, 01), + DoubleProp = 22.22 + }; + + var printer = ObjectPrinter.For() + .SetCulture(CultureInfo.InvariantCulture); + + Console.WriteLine(printer.PrintToString(cultureObject)); + + printer.PrintToString(cultureObject) + .Should() + .Be("CultureObject (\n\tDateTimeProp: 01/01/2020 00:00:00;\n\tDoubleProp: 22,22;\n)"); + } + + [Test] + public void SetCulture_WorksWithGivenProperty() + { + var cultureObject = new CultureObject + { + DateTimeProp = new DateTime(2020, 01, 01), + DoubleProp = 22.22 + }; + + var printer = ObjectPrinter.For() + .SetCulture(c => c.DoubleProp, CultureInfo.InvariantCulture); + + Console.WriteLine(printer.PrintToString(cultureObject)); + + printer.PrintToString(cultureObject) + .Should() + .Be("CultureObject (\n\tDateTimeProp: 01.01.2020 00:00:00;\n\tDoubleProp: 22.22;\n)"); + } + + [Test] + public void SliceStrings_Works() + { + var fullName = new FullName + { + Name = "SmallName", + Surname = "VeryBigSurNameWithALotOfWater", + }; + + var printer = ObjectPrinter.For() + .SliceStrings(10); + + printer.PrintToString(fullName) + .Should() + .Be("FullName (\n\tName: SmallName;\n\tSurname: VeryBigSur;\n)"); + } + + [Test] + public void PrintToString_WorksWithIEnumerable() + { + var arr = new[] { 1, 2 }; + + arr.PrintToString() + .Should() + .Be("[\n\t1,\n\t2,\n]"); + } + + [Test] + public void PrintToString_WorksWithNestedIEnumerable() + { + var arr = new[] { new []{1, 2}, new []{3, 4} }; + + arr.PrintToString() + .Should() + .Be("[\n\t[\n\t\t1,\n\t\t2,\n\t],\n\t[\n\t\t3,\n\t\t4,\n\t],\n]"); + } + + [Test] + public void PrintToString_WorksWithIDictionary() + { + var dict = new Dictionary + { + [1] = 1, + [2] = 4, + [3] = 9 + }; + + dict.PrintToString() + .Should() + .Be("{\n\t1: 1;\n\t2: 4;\n\t3: 9;\n}"); + } + + [Test] + public void PrintToString_WorksWithNestedIDictionary() + { + var dict = new Dictionary> + { + [1] = new () + { + [2] = 3, + [4] = 5, + }, + [6] = new () + { + [7] = 8, + [9] = 10, + }, + }; + + dict.PrintToString() + .Should() + .Be("{\n\t1: {\n\t\t2: 3;\n\t\t4: 5;\n\t};\n\t6: {\n\t\t7: 8;\n\t\t9: 10;\n\t};\n}"); + } + + [Test] + public void PropertyGettingMethod_ThrowsArgumentExceptionOnWrongExpression() + { + new Action(() => ObjectPrinter.For() + .Exclude(p => 4)) + .Should() + .ThrowExactly() + .Where(e => e.Message.Contains("MemberExpression")); + + new Action(() => ObjectPrinter.For() + .Select(p => 4)) + .Should() + .ThrowExactly() + .Where(e => e.Message.Contains("MemberExpression")); + } + + [Test] + public void PrintToString_HandlesCyclicLinks() + { + var obj1 = new CyclicObject {SomeProp = 30}; + + var obj2 = new CyclicObject {SomeProp = 50}; + + obj1.Another = obj2; + obj2.Another = obj1; + + obj1.PrintToString() + .Should() + .Be("CyclicObject (\n\tSomeProp: 30;\n\tAnother: CyclicObject (\n\t\tSomeProp: 50;\n\t\tAnother: cyclic link;\n\t);\n)"); + } +} \ No newline at end of file diff --git a/ObjectPrintingTests/ObjectPrintingTests.csproj b/ObjectPrintingTests/ObjectPrintingTests.csproj new file mode 100644 index 00000000..6ab58ff5 --- /dev/null +++ b/ObjectPrintingTests/ObjectPrintingTests.csproj @@ -0,0 +1,25 @@ + + + + net7.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + diff --git a/ObjectPrintingTests/Objects/CultureObject.cs b/ObjectPrintingTests/Objects/CultureObject.cs new file mode 100644 index 00000000..dd876099 --- /dev/null +++ b/ObjectPrintingTests/Objects/CultureObject.cs @@ -0,0 +1,7 @@ +namespace ObjectPrintingTests.Objects; + +public class CultureObject +{ + public DateTime DateTimeProp { get; set; } + public double DoubleProp { get; set; } +} \ No newline at end of file diff --git a/ObjectPrintingTests/Objects/CyclicObject.cs b/ObjectPrintingTests/Objects/CyclicObject.cs new file mode 100644 index 00000000..a20f4549 --- /dev/null +++ b/ObjectPrintingTests/Objects/CyclicObject.cs @@ -0,0 +1,7 @@ +namespace ObjectPrintingTests.Objects; + +public class CyclicObject +{ + public int SomeProp { get; set; } + public CyclicObject Another { get; set; } +} \ No newline at end of file diff --git a/ObjectPrintingTests/Objects/FullName.cs b/ObjectPrintingTests/Objects/FullName.cs new file mode 100644 index 00000000..af7a006c --- /dev/null +++ b/ObjectPrintingTests/Objects/FullName.cs @@ -0,0 +1,7 @@ +namespace ObjectPrintingTests.Objects; + +public class FullName +{ + public string Name { get; set; } + public string Surname { get; set; } +} \ No newline at end of file diff --git a/ObjectPrintingTests/Objects/Person.cs b/ObjectPrintingTests/Objects/Person.cs new file mode 100644 index 00000000..32b76f6f --- /dev/null +++ b/ObjectPrintingTests/Objects/Person.cs @@ -0,0 +1,11 @@ +namespace ObjectPrintingTests.Objects; + +public class Person +{ + public Guid Id { get; set; } + public string Name { get; set; } + public string Surname { get; set; } + public double Height { get; set; } + public int Age { get; set; } + public long Money { get; set; } +} \ No newline at end of file diff --git a/ObjectPrintingTests/Objects/Room.cs b/ObjectPrintingTests/Objects/Room.cs new file mode 100644 index 00000000..2c94a3af --- /dev/null +++ b/ObjectPrintingTests/Objects/Room.cs @@ -0,0 +1,8 @@ +namespace ObjectPrintingTests.Objects; + +public class Room +{ + public double Width { get; set; } + public double Length { get; set; } + public double Height { get; set; } +} \ No newline at end of file diff --git a/ObjectPrintingTests/Usings.cs b/ObjectPrintingTests/Usings.cs new file mode 100644 index 00000000..a83421a3 --- /dev/null +++ b/ObjectPrintingTests/Usings.cs @@ -0,0 +1,4 @@ +global using NUnit.Framework; +global using FluentAssertions; +global using ObjectPrinting; +global using ObjectPrintingTests.Objects; diff --git a/fluent-api.sln b/fluent-api.sln index 69c8db9e..b759236f 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", "{871B8341-3408-40B7-80CA-B5EBC1C507AF}" +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 + {871B8341-3408-40B7-80CA-B5EBC1C507AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {871B8341-3408-40B7-80CA-B5EBC1C507AF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {871B8341-3408-40B7-80CA-B5EBC1C507AF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {871B8341-3408-40B7-80CA-B5EBC1C507AF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 045edecf17e3be28a0979b7ad3830176fe4e5cbe Mon Sep 17 00:00:00 2001 From: caiman Date: Thu, 28 Dec 2023 17:02:14 +0500 Subject: [PATCH 3/6] refactored according to comments --- .../Extensions/EnumerableExtensions.cs | 25 +++--- .../Extensions/IDictionaryExtensions.cs | 14 +-- ObjectPrinting/Extensions/ObjectExtensions.cs | 10 +-- ObjectPrinting/ISerializer.cs | 11 --- .../Interfaces/IPropertySpecifier.cs | 9 ++ ObjectPrinting/Interfaces/ISerializer.cs | 8 ++ .../{ => Interfaces}/ISerializerSetter.cs | 2 +- ObjectPrinting/PrintingConfig.cs | 88 ++++--------------- ObjectPrinting/PropertySpecifier.cs | 30 +++++++ ObjectPrinting/Serializer.cs | 83 +++++++++++++---- ObjectPrintingTests/ObjectPrintingTests.cs | 66 ++++++++------ fluent-api.sln | 4 + 12 files changed, 194 insertions(+), 156 deletions(-) delete mode 100644 ObjectPrinting/ISerializer.cs create mode 100644 ObjectPrinting/Interfaces/IPropertySpecifier.cs create mode 100644 ObjectPrinting/Interfaces/ISerializer.cs rename ObjectPrinting/{ => Interfaces}/ISerializerSetter.cs (83%) create mode 100644 ObjectPrinting/PropertySpecifier.cs diff --git a/ObjectPrinting/Extensions/EnumerableExtensions.cs b/ObjectPrinting/Extensions/EnumerableExtensions.cs index 956558c8..0c6bf03e 100644 --- a/ObjectPrinting/Extensions/EnumerableExtensions.cs +++ b/ObjectPrinting/Extensions/EnumerableExtensions.cs @@ -1,46 +1,45 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; using System.Text; namespace ObjectPrinting.Extensions; public static class EnumerableExtensions { - public static string ObjectPrintEnumerable( + public static string ObjectPrint( this IEnumerable enumerable, - PrintingConfig printingConfig, + Serializer serializer, ImmutableList previous) { previous = previous.Add(enumerable); - return enumerable.EnumerateForObjectPrinting( + return enumerable.ObjectPrintingSerialize( "[", "]", - obj => $"{printingConfig.PrintToString1(obj, previous)},", - previous); + obj => $"{serializer.PrintToString(obj, previous)},", + previous.Count); } - public static string EnumerateForObjectPrinting( + public static string ObjectPrintingSerialize( this IEnumerable enumerable, string startSymbol, string endSymbol, - Func getRow, - ImmutableList previous) + Func elementSerializer, + int indentationLevel) { var sb = new StringBuilder(); sb.AppendLine(startSymbol); - var identation = new string('\t', previous.Count); + var indentation = new string('\t', indentationLevel); foreach (var obj in enumerable) { - sb.Append(identation); - sb.AppendLine(getRow(obj)); + sb.Append(indentation); + sb.AppendLine(elementSerializer(obj)); } - sb.Append(new string('\t', previous.Count - 1)); + sb.Append(new string('\t', indentationLevel - 1)); sb.Append(endSymbol); return sb.ToString(); diff --git a/ObjectPrinting/Extensions/IDictionaryExtensions.cs b/ObjectPrinting/Extensions/IDictionaryExtensions.cs index d6b11633..dc074a60 100644 --- a/ObjectPrinting/Extensions/IDictionaryExtensions.cs +++ b/ObjectPrinting/Extensions/IDictionaryExtensions.cs @@ -6,22 +6,22 @@ namespace ObjectPrinting.Extensions; public static class DictionaryExtensions { - public static string ObjectPrintDictionary( + public static string ObjectPrint( this IDictionary dictionary, - PrintingConfig printingConfig, + Serializer serializer, ImmutableList previous) { previous = previous.Add(dictionary); return dictionary - .KeysToValues() - .EnumerateForObjectPrinting( + .CastToDictionaryEntries() + .ObjectPrintingSerialize( "{", "}", - pair => $"{pair.Key}: {printingConfig.PrintToString1(pair.Value, previous)};", - previous); + pair => $"{pair.Key}: {serializer.PrintToString(pair.Value, previous)};", + previous.Count); } - private static IEnumerable KeysToValues(this IDictionary dictionary) + private static IEnumerable CastToDictionaryEntries(this IDictionary dictionary) { foreach (DictionaryEntry entry in dictionary) yield return entry; diff --git a/ObjectPrinting/Extensions/ObjectExtensions.cs b/ObjectPrinting/Extensions/ObjectExtensions.cs index edce1821..5c4ad366 100644 --- a/ObjectPrinting/Extensions/ObjectExtensions.cs +++ b/ObjectPrinting/Extensions/ObjectExtensions.cs @@ -2,13 +2,13 @@ namespace ObjectPrinting.Extensions; public static class ObjectExtensions { - public static string PrintToString(this T obj) + public static string PrintToString1(this T obj, PrintingConfig printingConfig) { - return ObjectPrinter.For().PrintToString(obj); + return new Serializer(printingConfig).PrintToString(obj); } - - public static string PrintToString(this T obj, PrintingConfig printingConfig) + + public static string PrintToString1(this T obj) { - return printingConfig.PrintToString(obj); + return new Serializer(ObjectPrinter.For()).PrintToString(obj); } } \ No newline at end of file diff --git a/ObjectPrinting/ISerializer.cs b/ObjectPrinting/ISerializer.cs deleted file mode 100644 index 4fb93d61..00000000 --- a/ObjectPrinting/ISerializer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Globalization; - -namespace ObjectPrinting -{ - public interface ISerializer - { - public PrintingConfig PrintingConfig { get; } - public PrintingConfig Serialize(Func serializer); - } -} \ No newline at end of file diff --git a/ObjectPrinting/Interfaces/IPropertySpecifier.cs b/ObjectPrinting/Interfaces/IPropertySpecifier.cs new file mode 100644 index 00000000..93c4636e --- /dev/null +++ b/ObjectPrinting/Interfaces/IPropertySpecifier.cs @@ -0,0 +1,9 @@ +using System; + +namespace ObjectPrinting.Interfaces +{ + public interface IPropertySpecifier + { + public PrintingConfig With(Func serializer); + } +} \ No newline at end of file diff --git a/ObjectPrinting/Interfaces/ISerializer.cs b/ObjectPrinting/Interfaces/ISerializer.cs new file mode 100644 index 00000000..4ba5bbf5 --- /dev/null +++ b/ObjectPrinting/Interfaces/ISerializer.cs @@ -0,0 +1,8 @@ +using System.Collections.Immutable; + +namespace ObjectPrinting.Interfaces; + +public interface ISerializer +{ + public string PrintToString(object obj, ImmutableList previous); +} \ No newline at end of file diff --git a/ObjectPrinting/ISerializerSetter.cs b/ObjectPrinting/Interfaces/ISerializerSetter.cs similarity index 83% rename from ObjectPrinting/ISerializerSetter.cs rename to ObjectPrinting/Interfaces/ISerializerSetter.cs index e7b8dab9..2a8fa214 100644 --- a/ObjectPrinting/ISerializerSetter.cs +++ b/ObjectPrinting/Interfaces/ISerializerSetter.cs @@ -1,7 +1,7 @@ using System; using System.Reflection; -namespace ObjectPrinting +namespace ObjectPrinting.Interfaces { public interface ISerializerSetter { diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 3af12c38..71935edb 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -1,13 +1,9 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.Collections.Immutable; using System.Globalization; -using System.Linq; using System.Linq.Expressions; using System.Reflection; -using System.Text; -using ObjectPrinting.Extensions; +using ObjectPrinting.Interfaces; namespace ObjectPrinting; @@ -31,28 +27,28 @@ public PrintingConfig Exclude(Expression> expression) return this; } - public ISerializer Select() + public IPropertySpecifier Serialize() { - return new Serializer(this); + return new PropertySpecifier(this); } - public ISerializer Select(Expression> expression) + public IPropertySpecifier Serialize(Expression> expression) { - return new Serializer(this, GetPropertyInfoFromExpression(expression)); + return new PropertySpecifier(this, GetPropertyInfoFromExpression(expression)); } public PrintingConfig SetCulture(CultureInfo cultureInfo) where T: IFormattable { - return Select() - .Serialize(obj => string.Format(cultureInfo, "{0}", obj)); + return Serialize() + .With(obj => string.Format(cultureInfo, "{0}", obj)); } public PrintingConfig SetCulture(Expression> expression, CultureInfo cultureInfo) where T: IFormattable { - return Select(expression) - .Serialize(obj => string.Format(cultureInfo, "{0}", obj)); + return Serialize(expression) + .With(obj => string.Format(cultureInfo, "{0}", obj)); } public PrintingConfig SliceStrings(int maxLength) @@ -60,8 +56,8 @@ public PrintingConfig SliceStrings(int maxLength) if (maxLength <= 0) throw new ArgumentException("Parameter maxLength must be positive"); - return Select() - .Serialize(s => maxLength >= s.Length ? s : s[..maxLength]); + return Serialize() + .With(s => maxLength >= s.Length ? s : s[..maxLength]); } void ISerializerSetter.SetSerializer(Func serializer, PropertyInfo propertyInfo) @@ -71,57 +67,8 @@ void ISerializerSetter.SetSerializer(Func serializer, PropertyInfo else typeSerializers[typeof(T)] = obj => serializer((T) obj); } - - public string PrintToString(TOwner obj) - { - return PrintToString1(obj, new List().ToImmutableList()); - } - - public string PrintToString1(object obj, ImmutableList previous) - { - if (obj == null) - return "null"; - - var type = obj.GetType(); - - if (TrySerializeValueType(type, obj, out var serializedValue)) - return serializedValue; - - if (IsCyclic(obj, previous)) - return "cyclic link"; - - if (obj is IDictionary dictionary) - return dictionary.ObjectPrintDictionary(this, previous); - - if (obj is IEnumerable enumerable) - return enumerable.Cast().ObjectPrintEnumerable(this, previous); - - var identation = new string('\t', previous.Count + 1); - previous = previous.Add(obj); - var sb = new StringBuilder(); - sb.AppendLine(type.Name + " ("); - foreach (var property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) - { - if (IsExcluded(property)) - continue; - - sb.Append($"{identation}{property.Name}: "); - - if (TrySerializeProperty(obj, property, out var serialized)) - sb.Append(serialized); - else - sb.Append(PrintToString1(property.GetValue(obj), previous)); - - sb.AppendLine(";"); - } - - sb.Append(new string('\t', previous.Count - 1) + ")"); - - return sb.ToString(); - } - - private bool TrySerializeValueType(Type type, object obj, out string serialized) + internal bool TrySerializeValueType(Type type, object obj, out string serialized) { serialized = ""; @@ -135,17 +82,12 @@ private bool TrySerializeValueType(Type type, object obj, out string serialized) return true; } - private bool IsCyclic(object current, IEnumerable previous) - { - return previous.Any(e => ReferenceEquals(e, current)); - } - - private bool IsExcluded(PropertyInfo propertyInfo) + internal bool IsExcluded(PropertyInfo propertyInfo) { return excludedProps.Contains(propertyInfo) || excludedTypes.Contains(propertyInfo.PropertyType); } - private bool TrySerializeProperty(object obj, PropertyInfo propertyInfo, out string serialized) + public bool TrySerializeProperty(object obj, PropertyInfo propertyInfo, out string serialized) { serialized = ""; @@ -156,7 +98,7 @@ private bool TrySerializeProperty(object obj, PropertyInfo propertyInfo, out str return true; } - private PropertyInfo GetPropertyInfoFromExpression(Expression> expression) + private static PropertyInfo GetPropertyInfoFromExpression(Expression> expression) { if (expression.Body is not MemberExpression memberExpression) throw new ArgumentException($"Expression {expression} is not MemberExpression"); diff --git a/ObjectPrinting/PropertySpecifier.cs b/ObjectPrinting/PropertySpecifier.cs new file mode 100644 index 00000000..143359c1 --- /dev/null +++ b/ObjectPrinting/PropertySpecifier.cs @@ -0,0 +1,30 @@ +using System; +using System.Reflection; +using ObjectPrinting.Interfaces; + +namespace ObjectPrinting +{ + public class PropertySpecifier : IPropertySpecifier + { + private PrintingConfig PrintingConfig { get; } + private readonly PropertyInfo propertyInfo; + + public PropertySpecifier(PrintingConfig printingConfig, PropertyInfo propertyInfo) + { + PrintingConfig = printingConfig; + this.propertyInfo = propertyInfo; + } + + public PropertySpecifier(PrintingConfig printingConfig) + { + PrintingConfig = printingConfig; + } + + public PrintingConfig With(Func serializer) + { + ((ISerializerSetter)PrintingConfig).SetSerializer(serializer, propertyInfo); + + return PrintingConfig; + } + } +} \ No newline at end of file diff --git a/ObjectPrinting/Serializer.cs b/ObjectPrinting/Serializer.cs index 7ee11720..75b0df8f 100644 --- a/ObjectPrinting/Serializer.cs +++ b/ObjectPrinting/Serializer.cs @@ -1,29 +1,74 @@ -using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; using System.Reflection; +using System.Text; +using ObjectPrinting.Extensions; +using ObjectPrinting.Interfaces; -namespace ObjectPrinting +namespace ObjectPrinting; + +public class Serializer : ISerializer { - public class Serializer : ISerializer + private readonly PrintingConfig printingConfig; + + public Serializer(PrintingConfig printingConfig) { - public PrintingConfig PrintingConfig { get; } - private readonly PropertyInfo propertyInfo; - - public Serializer(PrintingConfig printingConfig, PropertyInfo propertyInfo) - { - PrintingConfig = printingConfig; - this.propertyInfo = propertyInfo; - } + this.printingConfig = printingConfig; + } - public Serializer(PrintingConfig printingConfig) - { - PrintingConfig = printingConfig; - } - - public PrintingConfig Serialize(Func serializer) + public string PrintToString(T obj) + { + return PrintToString(obj, new List().ToImmutableList()); + } + + public string PrintToString(object obj, ImmutableList previous) + { + if (obj == null) + return "null"; + + var type = obj.GetType(); + + if (printingConfig.TrySerializeValueType(type, obj, out var serializedValue)) + return serializedValue; + + if (IsCyclic(obj, previous)) + return "cyclic link"; + + if (obj is IDictionary dictionary) + return dictionary.ObjectPrint(this, previous); + + if (obj is IEnumerable enumerable) + return enumerable.Cast().ObjectPrint(this, previous); + + var indentation = new string('\t', previous.Count + 1); + previous = previous.Add(obj); + var sb = new StringBuilder(); + sb.AppendLine(type.Name + " ("); + + foreach (var property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { - (PrintingConfig as ISerializerSetter).SetSerializer(serializer, propertyInfo); + if (printingConfig.IsExcluded(property)) + continue; - return PrintingConfig; + sb.Append($"{indentation}{property.Name}: "); + + if (printingConfig.TrySerializeProperty(obj, property, out var serialized)) + sb.Append(serialized); + else + sb.Append(PrintToString(property.GetValue(obj), previous)); + + sb.AppendLine(";"); } + + sb.Append(new string('\t', previous.Count - 1) + ")"); + + return sb.ToString(); + } + + private static bool IsCyclic(object current, IEnumerable previous) + { + return previous.Any(e => ReferenceEquals(e, current)); } } \ No newline at end of file diff --git a/ObjectPrintingTests/ObjectPrintingTests.cs b/ObjectPrintingTests/ObjectPrintingTests.cs index 4234d6d5..537da85e 100644 --- a/ObjectPrintingTests/ObjectPrintingTests.cs +++ b/ObjectPrintingTests/ObjectPrintingTests.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Drawing; using System.Globalization; using ObjectPrinting.Extensions; @@ -33,12 +33,12 @@ public void SetUp() [Test] public void Exclude_ExcludesGivenTypes() { - var printer = ObjectPrinter.For() + var config = ObjectPrinter.For() .Exclude() .Exclude() .Exclude(); - printer.PrintToString(person) + person.PrintToString1(config) .Should() .Be("Person (\n\tHeight: 180,5;\n\tAge: 19000000;\n)"); } @@ -46,12 +46,12 @@ public void Exclude_ExcludesGivenTypes() [Test] public void Exclude_ExcludesGivenProperties() { - var printer = ObjectPrinter.For() + var config = ObjectPrinter.For() .Exclude(p => p.Id) .Exclude(p => p.Name) .Exclude(p => p.Height); - printer.PrintToString(person) + person.PrintToString1(config) .Should() .Be("Person (\n\tSurname: Sinatra;\n\tAge: 19000000;\n\tMoney: 300;\n)"); } @@ -59,10 +59,10 @@ public void Exclude_ExcludesGivenProperties() [Test] public void Select_SerializesSpecifiedTypes() { - var printer = ObjectPrinter.For() - .Select().Serialize(num => Math.Ceiling(num).ToString()); + var config = ObjectPrinter.For() + .Serialize().With(num => Math.Ceiling(num).ToString()); - printer.PrintToString(room) + room.PrintToString1(config) .Should() .Be("Room (\n\tWidth: 33;\n\tLength: 49;\n\tHeight: 3;\n)"); } @@ -70,10 +70,10 @@ public void Select_SerializesSpecifiedTypes() [Test] public void Select_SerializesSpecifiedProperties() { - var printer = ObjectPrinter.For() - .Select(r => r.Height).Serialize(num => (num / 2).ToString()); + var config = ObjectPrinter.For() + .Serialize(r => r.Height).With(num => (num / 2).ToString()); - printer.PrintToString(room) + room.PrintToString1(config) .Should() .Be("Room (\n\tWidth: 32,5;\n\tLength: 48,6;\n\tHeight: 1,1;\n)"); } @@ -87,12 +87,10 @@ public void SetCulture_WorksWithGivenType() DoubleProp = 22.22 }; - var printer = ObjectPrinter.For() + var config = ObjectPrinter.For() .SetCulture(CultureInfo.InvariantCulture); - Console.WriteLine(printer.PrintToString(cultureObject)); - - printer.PrintToString(cultureObject) + cultureObject.PrintToString1(config) .Should() .Be("CultureObject (\n\tDateTimeProp: 01/01/2020 00:00:00;\n\tDoubleProp: 22,22;\n)"); } @@ -106,12 +104,10 @@ public void SetCulture_WorksWithGivenProperty() DoubleProp = 22.22 }; - var printer = ObjectPrinter.For() + var config = ObjectPrinter.For() .SetCulture(c => c.DoubleProp, CultureInfo.InvariantCulture); - Console.WriteLine(printer.PrintToString(cultureObject)); - - printer.PrintToString(cultureObject) + cultureObject.PrintToString1(config) .Should() .Be("CultureObject (\n\tDateTimeProp: 01.01.2020 00:00:00;\n\tDoubleProp: 22.22;\n)"); } @@ -125,10 +121,10 @@ public void SliceStrings_Works() Surname = "VeryBigSurNameWithALotOfWater", }; - var printer = ObjectPrinter.For() + var config = ObjectPrinter.For() .SliceStrings(10); - printer.PrintToString(fullName) + fullName.PrintToString1(config) .Should() .Be("FullName (\n\tName: SmallName;\n\tSurname: VeryBigSur;\n)"); } @@ -138,7 +134,7 @@ public void PrintToString_WorksWithIEnumerable() { var arr = new[] { 1, 2 }; - arr.PrintToString() + arr.PrintToString1() .Should() .Be("[\n\t1,\n\t2,\n]"); } @@ -148,7 +144,7 @@ public void PrintToString_WorksWithNestedIEnumerable() { var arr = new[] { new []{1, 2}, new []{3, 4} }; - arr.PrintToString() + arr.PrintToString1() .Should() .Be("[\n\t[\n\t\t1,\n\t\t2,\n\t],\n\t[\n\t\t3,\n\t\t4,\n\t],\n]"); } @@ -163,7 +159,7 @@ public void PrintToString_WorksWithIDictionary() [3] = 9 }; - dict.PrintToString() + dict.PrintToString1() .Should() .Be("{\n\t1: 1;\n\t2: 4;\n\t3: 9;\n}"); } @@ -185,7 +181,7 @@ public void PrintToString_WorksWithNestedIDictionary() }, }; - dict.PrintToString() + dict.PrintToString1() .Should() .Be("{\n\t1: {\n\t\t2: 3;\n\t\t4: 5;\n\t};\n\t6: {\n\t\t7: 8;\n\t\t9: 10;\n\t};\n}"); } @@ -200,7 +196,7 @@ public void PropertyGettingMethod_ThrowsArgumentExceptionOnWrongExpression() .Where(e => e.Message.Contains("MemberExpression")); new Action(() => ObjectPrinter.For() - .Select(p => 4)) + .Serialize(p => 4)) .Should() .ThrowExactly() .Where(e => e.Message.Contains("MemberExpression")); @@ -216,8 +212,24 @@ public void PrintToString_HandlesCyclicLinks() obj1.Another = obj2; obj2.Another = obj1; - obj1.PrintToString() + obj1.PrintToString1() .Should() .Be("CyclicObject (\n\tSomeProp: 30;\n\tAnother: CyclicObject (\n\t\tSomeProp: 50;\n\t\tAnother: cyclic link;\n\t);\n)"); } + + [Test] + public void PrintToString_WorksWithStrings() + { + "serialize me".PrintToString1() + .Should() + .Be("serialize me"); + } + + [Test] + public void PrintToString_WorksWithValueTypes() + { + new Point(1, 1).PrintToString1() + .Should() + .Be("{X=1,Y=1}"); + } } \ No newline at end of file diff --git a/fluent-api.sln b/fluent-api.sln index b759236f..d753c5a7 100644 --- a/fluent-api.sln +++ b/fluent-api.sln @@ -15,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spectacle", "Samples\Specta EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObjectPrintingTests", "ObjectPrintingTests\ObjectPrintingTests.csproj", "{871B8341-3408-40B7-80CA-B5EBC1C507AF}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ObjectPrinting", "ObjectPrinting", "{770E7FC3-D26C-459C-A84C-1F31A8F5717A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -49,5 +51,7 @@ Global {FEEA5AFE-459A-4D13-81D0-252E1A2E6F4E} = {6D308E4A-CEC7-4536-9B87-81CD337A87AD} {8A7BB3EA-3E6A-4D04-A801-D5CD1620DA0D} = {6D308E4A-CEC7-4536-9B87-81CD337A87AD} {EFA9335C-411B-4597-B0B6-5438D1AE04C3} = {6D308E4A-CEC7-4536-9B87-81CD337A87AD} + {07B8C9B7-8289-46CB-9875-048A57758EEE} = {770E7FC3-D26C-459C-A84C-1F31A8F5717A} + {871B8341-3408-40B7-80CA-B5EBC1C507AF} = {770E7FC3-D26C-459C-A84C-1F31A8F5717A} EndGlobalSection EndGlobal From e046be5374cd82b7aa963edb999138bd66b202f0 Mon Sep 17 00:00:00 2001 From: caiman Date: Thu, 28 Dec 2023 17:09:02 +0500 Subject: [PATCH 4/6] added method PrintToString to ISerializer --- ObjectPrinting/Interfaces/ISerializer.cs | 3 ++- ObjectPrinting/Serializer.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ObjectPrinting/Interfaces/ISerializer.cs b/ObjectPrinting/Interfaces/ISerializer.cs index 4ba5bbf5..072607bf 100644 --- a/ObjectPrinting/Interfaces/ISerializer.cs +++ b/ObjectPrinting/Interfaces/ISerializer.cs @@ -2,7 +2,8 @@ namespace ObjectPrinting.Interfaces; -public interface ISerializer +public interface ISerializer { public string PrintToString(object obj, ImmutableList previous); + public string PrintToString(T obj); } \ No newline at end of file diff --git a/ObjectPrinting/Serializer.cs b/ObjectPrinting/Serializer.cs index 75b0df8f..d35ab55b 100644 --- a/ObjectPrinting/Serializer.cs +++ b/ObjectPrinting/Serializer.cs @@ -9,7 +9,7 @@ namespace ObjectPrinting; -public class Serializer : ISerializer +public class Serializer : ISerializer { private readonly PrintingConfig printingConfig; From e75c828dfdf1fed8445bb40829a49145992d7cc9 Mon Sep 17 00:00:00 2001 From: caiman Date: Thu, 28 Dec 2023 17:10:31 +0500 Subject: [PATCH 5/6] refactored namings --- ObjectPrinting/Extensions/ObjectExtensions.cs | 4 +-- ObjectPrintingTests/ObjectPrintingTests.cs | 28 +++++++++---------- Test/Program.cs | 10 +++++++ Test/Test.csproj | 10 +++++++ 4 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 Test/Program.cs create mode 100644 Test/Test.csproj diff --git a/ObjectPrinting/Extensions/ObjectExtensions.cs b/ObjectPrinting/Extensions/ObjectExtensions.cs index 5c4ad366..dd89946b 100644 --- a/ObjectPrinting/Extensions/ObjectExtensions.cs +++ b/ObjectPrinting/Extensions/ObjectExtensions.cs @@ -2,12 +2,12 @@ namespace ObjectPrinting.Extensions; public static class ObjectExtensions { - public static string PrintToString1(this T obj, PrintingConfig printingConfig) + public static string PrintToString(this T obj, PrintingConfig printingConfig) { return new Serializer(printingConfig).PrintToString(obj); } - public static string PrintToString1(this T obj) + public static string PrintToString(this T obj) { return new Serializer(ObjectPrinter.For()).PrintToString(obj); } diff --git a/ObjectPrintingTests/ObjectPrintingTests.cs b/ObjectPrintingTests/ObjectPrintingTests.cs index 537da85e..3826b023 100644 --- a/ObjectPrintingTests/ObjectPrintingTests.cs +++ b/ObjectPrintingTests/ObjectPrintingTests.cs @@ -38,7 +38,7 @@ public void Exclude_ExcludesGivenTypes() .Exclude() .Exclude(); - person.PrintToString1(config) + person.PrintToString(config) .Should() .Be("Person (\n\tHeight: 180,5;\n\tAge: 19000000;\n)"); } @@ -51,7 +51,7 @@ public void Exclude_ExcludesGivenProperties() .Exclude(p => p.Name) .Exclude(p => p.Height); - person.PrintToString1(config) + person.PrintToString(config) .Should() .Be("Person (\n\tSurname: Sinatra;\n\tAge: 19000000;\n\tMoney: 300;\n)"); } @@ -62,7 +62,7 @@ public void Select_SerializesSpecifiedTypes() var config = ObjectPrinter.For() .Serialize().With(num => Math.Ceiling(num).ToString()); - room.PrintToString1(config) + room.PrintToString(config) .Should() .Be("Room (\n\tWidth: 33;\n\tLength: 49;\n\tHeight: 3;\n)"); } @@ -73,7 +73,7 @@ public void Select_SerializesSpecifiedProperties() var config = ObjectPrinter.For() .Serialize(r => r.Height).With(num => (num / 2).ToString()); - room.PrintToString1(config) + room.PrintToString(config) .Should() .Be("Room (\n\tWidth: 32,5;\n\tLength: 48,6;\n\tHeight: 1,1;\n)"); } @@ -90,7 +90,7 @@ public void SetCulture_WorksWithGivenType() var config = ObjectPrinter.For() .SetCulture(CultureInfo.InvariantCulture); - cultureObject.PrintToString1(config) + cultureObject.PrintToString(config) .Should() .Be("CultureObject (\n\tDateTimeProp: 01/01/2020 00:00:00;\n\tDoubleProp: 22,22;\n)"); } @@ -107,7 +107,7 @@ public void SetCulture_WorksWithGivenProperty() var config = ObjectPrinter.For() .SetCulture(c => c.DoubleProp, CultureInfo.InvariantCulture); - cultureObject.PrintToString1(config) + cultureObject.PrintToString(config) .Should() .Be("CultureObject (\n\tDateTimeProp: 01.01.2020 00:00:00;\n\tDoubleProp: 22.22;\n)"); } @@ -124,7 +124,7 @@ public void SliceStrings_Works() var config = ObjectPrinter.For() .SliceStrings(10); - fullName.PrintToString1(config) + fullName.PrintToString(config) .Should() .Be("FullName (\n\tName: SmallName;\n\tSurname: VeryBigSur;\n)"); } @@ -134,7 +134,7 @@ public void PrintToString_WorksWithIEnumerable() { var arr = new[] { 1, 2 }; - arr.PrintToString1() + arr.PrintToString() .Should() .Be("[\n\t1,\n\t2,\n]"); } @@ -144,7 +144,7 @@ public void PrintToString_WorksWithNestedIEnumerable() { var arr = new[] { new []{1, 2}, new []{3, 4} }; - arr.PrintToString1() + arr.PrintToString() .Should() .Be("[\n\t[\n\t\t1,\n\t\t2,\n\t],\n\t[\n\t\t3,\n\t\t4,\n\t],\n]"); } @@ -159,7 +159,7 @@ public void PrintToString_WorksWithIDictionary() [3] = 9 }; - dict.PrintToString1() + dict.PrintToString() .Should() .Be("{\n\t1: 1;\n\t2: 4;\n\t3: 9;\n}"); } @@ -181,7 +181,7 @@ public void PrintToString_WorksWithNestedIDictionary() }, }; - dict.PrintToString1() + dict.PrintToString() .Should() .Be("{\n\t1: {\n\t\t2: 3;\n\t\t4: 5;\n\t};\n\t6: {\n\t\t7: 8;\n\t\t9: 10;\n\t};\n}"); } @@ -212,7 +212,7 @@ public void PrintToString_HandlesCyclicLinks() obj1.Another = obj2; obj2.Another = obj1; - obj1.PrintToString1() + obj1.PrintToString() .Should() .Be("CyclicObject (\n\tSomeProp: 30;\n\tAnother: CyclicObject (\n\t\tSomeProp: 50;\n\t\tAnother: cyclic link;\n\t);\n)"); } @@ -220,7 +220,7 @@ public void PrintToString_HandlesCyclicLinks() [Test] public void PrintToString_WorksWithStrings() { - "serialize me".PrintToString1() + "serialize me".PrintToString() .Should() .Be("serialize me"); } @@ -228,7 +228,7 @@ public void PrintToString_WorksWithStrings() [Test] public void PrintToString_WorksWithValueTypes() { - new Point(1, 1).PrintToString1() + new Point(1, 1).PrintToString() .Should() .Be("{X=1,Y=1}"); } diff --git a/Test/Program.cs b/Test/Program.cs new file mode 100644 index 00000000..6787bbdb --- /dev/null +++ b/Test/Program.cs @@ -0,0 +1,10 @@ +// See https://aka.ms/new-console-template for more information + +Func a = (A item) => item.id; + + + +class A +{ + public int id; +} \ No newline at end of file diff --git a/Test/Test.csproj b/Test/Test.csproj new file mode 100644 index 00000000..2b14c817 --- /dev/null +++ b/Test/Test.csproj @@ -0,0 +1,10 @@ + + + + Exe + net7.0 + enable + enable + + + From 5e076d07d256088446e9e81e7042e232cefd0ba6 Mon Sep 17 00:00:00 2001 From: caiman Date: Thu, 28 Dec 2023 17:14:00 +0500 Subject: [PATCH 6/6] added internal to method --- ObjectPrinting/PrintingConfig.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ObjectPrinting/PrintingConfig.cs b/ObjectPrinting/PrintingConfig.cs index 71935edb..ec61e90d 100644 --- a/ObjectPrinting/PrintingConfig.cs +++ b/ObjectPrinting/PrintingConfig.cs @@ -87,7 +87,7 @@ internal bool IsExcluded(PropertyInfo propertyInfo) return excludedProps.Contains(propertyInfo) || excludedTypes.Contains(propertyInfo.PropertyType); } - public bool TrySerializeProperty(object obj, PropertyInfo propertyInfo, out string serialized) + internal bool TrySerializeProperty(object obj, PropertyInfo propertyInfo, out string serialized) { serialized = "";