Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Холстинин Егор #188

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace ObjectPrinting.Solved
namespace ObjectPrinting
{
public static class ObjectExtensions
{
Expand Down
5 changes: 0 additions & 5 deletions ObjectPrinting/ObjectPrinting.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,4 @@
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="NUnit" Version="3.12.0" />
</ItemGroup>

</Project>
119 changes: 104 additions & 15 deletions ObjectPrinting/PrintingConfig.cs
Original file line number Diff line number Diff line change
@@ -1,41 +1,130 @@
using System;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace ObjectPrinting
{
public class PrintingConfig<TOwner>
{
private readonly HashSet<Type> excludedTypes = new HashSet<Type>();
private readonly HashSet<PropertyInfo> excludedProperties = new HashSet<PropertyInfo>();

internal readonly Dictionary<Type, Func<object, string>> typeSerializers =
new Dictionary<Type, Func<object, string>>();

internal readonly Dictionary<PropertyInfo, Func<object, string>> propertySerializers =
new Dictionary<PropertyInfo, Func<object, string>>();

public TypePrintingConfig<TOwner, TPropType> Printing<TPropType>()
{
return new TypePrintingConfig<TOwner, TPropType>(this);
}

public PropertyPrintingConfig<TOwner, TPropType> Printing<TPropType>(Expression<Func<TOwner, TPropType>> memberSelector)
{
var propInfo = ((MemberExpression)memberSelector.Body).Member as PropertyInfo;
return new PropertyPrintingConfig<TOwner, TPropType>(this, propInfo);
}

public PrintingConfig<TOwner> Excluding<TPropType>(Expression<Func<TOwner, TPropType>> memberSelector)
{
var propInfo = ((MemberExpression)memberSelector.Body).Member as PropertyInfo;
excludedProperties.Add(propInfo);
return this;
}

public PrintingConfig<TOwner> Excluding<TPropType>()
{
excludedTypes.Add(typeof(TPropType));
return this;
}

public string PrintToString(TOwner obj)
{
return PrintToString(obj, 0);
return PrintToString(obj, ImmutableHashSet<object>.Empty);
}

private string PrintToString(object obj, int nestingLevel)
private string SerializeIEnumerable(IEnumerable enumerable, ImmutableHashSet<object> nestedObjects)
{
var sb = new StringBuilder();
if (enumerable is IDictionary dictionary)
return SerializeIDictionary(dictionary, nestedObjects);
sb.Append("[ ");
foreach (var element in enumerable)
{
sb.Append(PrintToString(element, nestedObjects).TrimEnd());
sb.Append(" ");
}

sb.Append("]");
return sb.ToString();
}

private string SerializeIDictionary(IDictionary dictionary, ImmutableHashSet<object> nestedObjects)
{
var sb = new StringBuilder();
var identation = new string('\t', nestedObjects.Count);
sb.Append(identation + "{" + Environment.NewLine);
nestedObjects = nestedObjects.Add(dictionary);
foreach (DictionaryEntry dictionaryEntry in dictionary)
{
sb.Append(identation + "\t[" + Environment.NewLine);
sb.Append("\t" + PrintToString(dictionaryEntry.Key, nestedObjects));
sb.Append(identation + "\t:" + Environment.NewLine);
sb.Append("\t" + PrintToString(dictionaryEntry.Value, nestedObjects));
sb.Append(identation + "\t]," + Environment.NewLine);
}

sb.Append(identation + "}" + Environment.NewLine);
return sb.ToString().TrimEnd();
}

private string PrintToString(object obj, ImmutableHashSet<object> nestedObjects)
{
//TODO apply configurations
if (obj == null)
return "null" + Environment.NewLine;

var finalTypes = new[]
var objType = obj.GetType();
if (obj.GetType().IsValueType || obj is string)
{
typeof(int), typeof(double), typeof(float), typeof(string),
typeof(DateTime), typeof(TimeSpan)
};
if (finalTypes.Contains(obj.GetType()))
if (typeSerializers.TryGetValue(objType, out var serializer))
return serializer(obj) + Environment.NewLine;
return obj + Environment.NewLine;
}

var identation = new string('\t', nestingLevel + 1);
if (obj is IEnumerable enumerable)
return SerializeIEnumerable(enumerable, nestedObjects) + Environment.NewLine;

var identation = new string('\t', nestedObjects.Count + 1);
var sb = new StringBuilder();
var type = obj.GetType();
sb.AppendLine(type.Name);
foreach (var propertyInfo in type.GetProperties())
sb.AppendLine(objType.Name);
nestedObjects = nestedObjects.Add(obj);
foreach (var propertyInfo in objType.GetProperties())
{
var propertyValue = propertyInfo.GetValue(obj);
if (ExcludedFromSerialization(propertyInfo) || nestedObjects.Contains(propertyValue))
continue;

if (propertySerializers.TryGetValue(propertyInfo, out var serializer))
{
sb.Append(identation + propertyInfo.Name + " = " + serializer(propertyValue) + Environment.NewLine);
continue;
}

sb.Append(identation + propertyInfo.Name + " = " +
PrintToString(propertyInfo.GetValue(obj),
nestingLevel + 1));
PrintToString(propertyInfo.GetValue(obj), nestedObjects));
}
return sb.ToString();
}

private bool ExcludedFromSerialization(PropertyInfo propertyInfo)
{
return excludedTypes.Contains(propertyInfo.PropertyType) || excludedProperties.Contains(propertyInfo);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
using System;
using System.Globalization;
using System.Reflection;

namespace ObjectPrinting.Solved
namespace ObjectPrinting
{
public class PropertyPrintingConfig<TOwner, TPropType> : IPropertyPrintingConfig<TOwner, TPropType>
{
private readonly PrintingConfig<TOwner> printingConfig;
public PrintingConfig<TOwner> PrintingConfig { get; }
public PropertyInfo PropertyInfo { get; }

public PropertyPrintingConfig(PrintingConfig<TOwner> printingConfig)
public PropertyPrintingConfig(PrintingConfig<TOwner> printingConfig, PropertyInfo propertyInfo)
{
this.printingConfig = printingConfig;
this.PrintingConfig = printingConfig;
this.PropertyInfo = propertyInfo;
}

public PrintingConfig<TOwner> Using(Func<TPropType, string> print)
{
return printingConfig;
var castedFunc = new Func<object, string>((obj) => print((TPropType)obj));
PrintingConfig.propertySerializers.Add(PropertyInfo, castedFunc);
return PrintingConfig;
}

public PrintingConfig<TOwner> Using(CultureInfo culture)
{
return printingConfig;
}

PrintingConfig<TOwner> IPropertyPrintingConfig<TOwner, TPropType>.ParentConfig => printingConfig;
PrintingConfig<TOwner> IPropertyPrintingConfig<TOwner, TPropType>.ParentConfig => PrintingConfig;
}

public interface IPropertyPrintingConfig<TOwner, TPropType>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Reflection;
using System.Text.RegularExpressions;

namespace ObjectPrinting.Solved
namespace ObjectPrinting
{
public static class PropertyPrintingConfigExtensions
{
Expand All @@ -11,7 +13,11 @@ public static string PrintToString<T>(this T obj, Func<PrintingConfig<T>, Printi

public static PrintingConfig<TOwner> TrimmedToLength<TOwner>(this PropertyPrintingConfig<TOwner, string> propConfig, int maxLen)
{
return ((IPropertyPrintingConfig<TOwner, string>)propConfig).ParentConfig;
var culturedFunc = new Func<string, string>(s => s[..Math.Min(maxLen, s.Length)]);
var castedFunc = new Func<object, string>(obj => culturedFunc((string)obj));
var parent = propConfig.PrintingConfig;
parent.propertySerializers.Add(propConfig.PropertyInfo, castedFunc);
return parent;
}

}
Expand Down
10 changes: 0 additions & 10 deletions ObjectPrinting/Solved/ObjectPrinter.cs

This file was deleted.

62 changes: 0 additions & 62 deletions ObjectPrinting/Solved/PrintingConfig.cs

This file was deleted.

40 changes: 0 additions & 40 deletions ObjectPrinting/Solved/Tests/ObjectPrinterAcceptanceTests.cs

This file was deleted.

27 changes: 0 additions & 27 deletions ObjectPrinting/Tests/ObjectPrinterAcceptanceTests.cs

This file was deleted.

12 changes: 0 additions & 12 deletions ObjectPrinting/Tests/Person.cs

This file was deleted.

Loading