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 7 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>
125 changes: 110 additions & 15 deletions ObjectPrinting/PrintingConfig.cs
Original file line number Diff line number Diff line change
@@ -1,41 +1,136 @@
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> excludedProperites = new HashSet<PropertyInfo>();

Yrwlcm marked this conversation as resolved.
Show resolved Hide resolved
private readonly Type[] finalTypes =
{
typeof(int), typeof(double), typeof(float), typeof(string),
typeof(DateTime), typeof(TimeSpan)
};

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;
excludedProperites.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)
return SerializeIDictionary((IDictionary)enumerable, nestedObjects);
Yrwlcm marked this conversation as resolved.
Show resolved Hide resolved
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 (finalTypes.Contains(objType))
{
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;
}
Yrwlcm marked this conversation as resolved.
Show resolved Hide resolved

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 (Excluded(propertyInfo) || nestedObjects.Contains(propertyValue))
continue;
Yrwlcm marked this conversation as resolved.
Show resolved Hide resolved

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 Excluded(PropertyInfo propertyInfo)
{
return excludedTypes.Contains(propertyInfo.PropertyType) || excludedProperites.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