-
Notifications
You must be signed in to change notification settings - Fork 215
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
Бабин Георгий #191
base: master
Are you sure you want to change the base?
Бабин Георгий #191
Changes from 6 commits
b76def7
13bcda8
7acf58c
757c9d4
a3b5c0b
52faebf
d61444b
17c9422
5c421ec
1b26dfc
7efdca1
49ce2b7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using System; | ||
using System.Globalization; | ||
using ObjectPrinting.InnerPrintingConfig; | ||
|
||
namespace ObjectPrinting.Extensions | ||
{ | ||
public static class InnerPrintingConfigExtensions | ||
{ | ||
public static PrintingConfig<TOwner> Using<TOwner>(this IInnerPrintingConfig<TOwner, double> typeConfig, CultureInfo culture) | ||
{ | ||
typeConfig.ParentConfig.TypeSerializers[typeof(double)] = obj => ((double) obj).ToString(culture); | ||
return typeConfig.ParentConfig; | ||
} | ||
|
||
public static PrintingConfig<TOwner> Using<TOwner>(this IInnerPrintingConfig<TOwner, DateTime> typeConfig, CultureInfo culture) | ||
{ | ||
typeConfig.ParentConfig.TypeSerializers[typeof(DateTime)] = obj => ((DateTime) obj).ToString(culture); | ||
return typeConfig.ParentConfig; | ||
} | ||
|
||
public static PrintingConfig<TOwner> Using<TOwner>(this IInnerPrintingConfig<TOwner, float> typeConfig, CultureInfo culture) | ||
{ | ||
typeConfig.ParentConfig.TypeSerializers[typeof(float)] = obj => ((float) obj).ToString(culture); | ||
return typeConfig.ParentConfig; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System; | ||
|
||
namespace ObjectPrinting.Extensions | ||
{ | ||
public static class ObjectExtensions | ||
{ | ||
public static string PrintToString<T>(this T obj) | ||
{ | ||
return ObjectPrinter.For<T>().PrintToString(obj); | ||
} | ||
|
||
public static string PrintToString<T>(this T obj, Func<PrintingConfig<T>, PrintingConfig<T>> config) | ||
{ | ||
return config(ObjectPrinter.For<T>()).PrintToString(obj); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace ObjectPrinting.Extensions | ||
{ | ||
public static class StringExtensions | ||
{ | ||
public static string Truncate(this string text, int maxLength, string truncationSuffix = "") | ||
{ | ||
return text.Length > maxLength | ||
? text[..maxLength] + truncationSuffix | ||
: text; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using ObjectPrinting.PropertyOrField; | ||
|
||
namespace ObjectPrinting.Extensions | ||
{ | ||
public static class TypeExtensions | ||
{ | ||
public static IEnumerable<IPropertyOrField> GetFieldsAndProperties(this Type type, BindingFlags bindingAttr) | ||
{ | ||
return type.GetFields(bindingAttr) | ||
.Select(x => new PropertyOrField.PropertyOrField(x)) | ||
.Concat(type.GetProperties(bindingAttr).Select(x => new PropertyOrField.PropertyOrField(x))); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace ObjectPrinting.InnerPrintingConfig | ||
{ | ||
public interface IInnerPrintingConfig<TOwner, TTypeOrPropType> | ||
{ | ||
PrintingConfig<TOwner> ParentConfig { get; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
using System; | ||
using System.Reflection; | ||
using ObjectPrinting.Extensions; | ||
|
||
namespace ObjectPrinting.InnerPrintingConfig | ||
{ | ||
public class MemberPrintingConfig<TOwner, TMemberType> : IInnerPrintingConfig<TOwner, TMemberType> | ||
{ | ||
private readonly PrintingConfig<TOwner> printingConfig; | ||
PrintingConfig<TOwner> IInnerPrintingConfig<TOwner, TMemberType>.ParentConfig => printingConfig; | ||
private readonly MemberInfo memberInfo; | ||
|
||
public MemberPrintingConfig(PrintingConfig<TOwner> printingConfig, MemberInfo memberInfo) | ||
{ | ||
this.printingConfig = printingConfig; | ||
this.memberInfo = memberInfo; | ||
} | ||
|
||
public PrintingConfig<TOwner> Using(Func<TMemberType, string> print) | ||
{ | ||
printingConfig.MemberSerializers[memberInfo] = obj => print((TMemberType)obj); | ||
return printingConfig; | ||
} | ||
|
||
public PrintingConfig<TOwner> TrimmedToLength(int maxLen) | ||
{ | ||
var isSerialized = printingConfig.MemberSerializers.TryGetValue(memberInfo, out var prevSerializer); | ||
printingConfig.MemberSerializers[memberInfo] = isSerialized | ||
? obj => prevSerializer(obj).Truncate(maxLen) | ||
: obj => obj.ToString().Truncate(maxLen); | ||
|
||
return printingConfig; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System; | ||
using ObjectPrinting.Extensions; | ||
|
||
namespace ObjectPrinting.InnerPrintingConfig | ||
{ | ||
public class TypePrintingConfig<TOwner, TType> : IInnerPrintingConfig<TOwner, TType> | ||
{ | ||
private readonly PrintingConfig<TOwner> printingConfig; | ||
PrintingConfig<TOwner> IInnerPrintingConfig<TOwner, TType>.ParentConfig => printingConfig; | ||
|
||
public TypePrintingConfig(PrintingConfig<TOwner> printingConfig) | ||
{ | ||
this.printingConfig = printingConfig; | ||
} | ||
|
||
public PrintingConfig<TOwner> Using(Func<TType, string> print) | ||
{ | ||
printingConfig.TypeSerializers[typeof(TType)] = obj => print((TType)obj); | ||
return printingConfig; | ||
} | ||
|
||
public PrintingConfig<TOwner> TrimmedToLength(int maxLen) | ||
{ | ||
var isSerialized = printingConfig.TypeSerializers.TryGetValue(typeof(TType), out var prevSerializer); | ||
printingConfig.TypeSerializers[typeof(TType)] = isSerialized | ||
? obj => prevSerializer(obj).Truncate(maxLen) | ||
: obj => obj.ToString().Truncate(maxLen); | ||
return printingConfig; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
namespace ObjectPrinting | ||
{ | ||
public class ObjectPrinter | ||
public static class ObjectPrinter | ||
{ | ||
public static PrintingConfig<T> For<T>() | ||
public static PrintingConfig<T> For<T>(int maxNestingLevel = 10) | ||
{ | ||
return new PrintingConfig<T>(); | ||
return new PrintingConfig<T>(maxNestingLevel); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,82 @@ | ||
using System; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Linq.Expressions; | ||
using System.Reflection; | ||
using System.Text; | ||
using ObjectPrinting.Extensions; | ||
using ObjectPrinting.InnerPrintingConfig; | ||
|
||
namespace ObjectPrinting | ||
{ | ||
public class PrintingConfig<TOwner> | ||
{ | ||
private readonly Type[] finalTypes = | ||
{ | ||
typeof(int), typeof(double), typeof(float), typeof(string), | ||
typeof(DateTime), typeof(TimeSpan), typeof(Guid) | ||
}; | ||
private readonly HashSet<Type> excludedTypes = new(); | ||
private readonly HashSet<MemberInfo> excludedMembers = new(); | ||
internal readonly Dictionary<Type, Func<object, string>> TypeSerializers = new(); | ||
internal readonly Dictionary<MemberInfo, Func<object, string>> MemberSerializers = new(); | ||
private int MaxNestingLevel { get; } | ||
public PrintingConfig(int maxNestingLevel = 10) | ||
{ | ||
MaxNestingLevel = maxNestingLevel; | ||
} | ||
|
||
public TypePrintingConfig<TOwner, TType> Printing<TType>() | ||
{ | ||
return new TypePrintingConfig<TOwner, TType>(this); | ||
} | ||
|
||
public MemberPrintingConfig<TOwner, TMemberType> Printing<TMemberType>(Expression<Func<TOwner, TMemberType>> memberSelector) | ||
{ | ||
var memberInfo = ((MemberExpression) memberSelector.Body).Member; | ||
return new MemberPrintingConfig<TOwner, TMemberType>(this, memberInfo); | ||
} | ||
|
||
public PrintingConfig<TOwner> Excluding<TMemberType>(Expression<Func<TOwner, TMemberType>> memberSelector) | ||
{ | ||
var memberInfo = ((MemberExpression) memberSelector.Body).Member; | ||
excludedMembers.Add(memberInfo); | ||
return Excluding<TMemberType>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Сейчас логика работает так, что если я исключаю какое-то конкретное поле, то исключаются все поля этого типа тоже. Похоже на какую-то опечатку. |
||
} | ||
|
||
public PrintingConfig<TOwner> Excluding<TType>() | ||
{ | ||
excludedTypes.Add(typeof(TType)); | ||
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())) | ||
var type = obj.GetType(); | ||
|
||
if (TypeSerializers.TryGetValue(obj.GetType(), out var serializer)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А почему тут не переменная type используется? |
||
return serializer(obj) + Environment.NewLine; | ||
if (finalTypes.Contains(type) || nestingLevel == MaxNestingLevel) | ||
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()) | ||
var sb = new StringBuilder(type.Name + Environment.NewLine); | ||
foreach (var propertyOrField in type.GetFieldsAndProperties(BindingFlags.Instance | BindingFlags.Public).Where(x => !excludedMembers.Contains(x.UnderlyingMember) && !excludedTypes.Contains(x.DataType))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Давай вот это вот большое in (...) вынесем в отдельную переменную? Как-то уж слишком страшно выглядит. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Выделил в метод в новом коммите) |
||
{ | ||
sb.Append(identation + propertyInfo.Name + " = " + | ||
PrintToString(propertyInfo.GetValue(obj), | ||
nestingLevel + 1)); | ||
sb.Append(identation + propertyOrField.Name + " = " + | ||
(MemberSerializers.TryGetValue(propertyOrField.UnderlyingMember, out var propertyOrFieldSerializer) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Давай конечную сериализацию вынесем тоже в отдельную переменную? Начиная с (MemberSerializers. ... |
||
? propertyOrFieldSerializer(propertyOrField.GetValue(obj)) + Environment.NewLine | ||
: PrintToString(propertyOrField.GetValue(obj), nestingLevel + 1))); | ||
} | ||
|
||
return sb.ToString(); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
using System.Reflection; | ||
|
||
namespace ObjectPrinting.PropertyOrField | ||
{ | ||
public interface IPropertyOrField | ||
{ | ||
string Name { get; } | ||
Type DataType { get; } | ||
MemberInfo UnderlyingMember { get; } | ||
Func<object, object> GetValue { get; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using System; | ||
using System.Reflection; | ||
|
||
namespace ObjectPrinting.PropertyOrField | ||
{ | ||
public class PropertyOrField : IPropertyOrField | ||
{ | ||
public string Name { get; } | ||
public Type DataType { get; } | ||
public MemberInfo UnderlyingMember { get; } | ||
public Func<object, object> GetValue { get; } | ||
|
||
public PropertyOrField(PropertyInfo propertyInfo) | ||
{ | ||
Name = propertyInfo.Name; | ||
DataType = propertyInfo.PropertyType; | ||
UnderlyingMember = propertyInfo; | ||
GetValue = propertyInfo.GetValue; | ||
} | ||
|
||
public PropertyOrField(FieldInfo fieldInfo) | ||
{ | ||
Name = fieldInfo.Name; | ||
DataType = fieldInfo.FieldType; | ||
UnderlyingMember = fieldInfo; | ||
GetValue = fieldInfo.GetValue; | ||
} | ||
} | ||
} |
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не очень хорошо, что можно получить доступ к этим полям вне класса.