-
Notifications
You must be signed in to change notification settings - Fork 214
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
Шевелев Георгий #201
base: master
Are you sure you want to change the base?
Шевелев Георгий #201
Changes from 2 commits
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,24 @@ | ||
using System; | ||
using System.Reflection; | ||
|
||
namespace ObjectPrinting.Extensions | ||
{ | ||
public static class MemberExtensions | ||
{ | ||
internal static Type GetMemberType(this MemberInfo memberInfo) => | ||
memberInfo.MemberType switch | ||
{ | ||
MemberTypes.Property => ((PropertyInfo)memberInfo).PropertyType, | ||
MemberTypes.Field => ((FieldInfo)memberInfo).FieldType, | ||
_ => throw new NotImplementedException($"Getting type of {memberInfo.MemberType} is not implemented") | ||
}; | ||
|
||
public static object GetValue(this MemberInfo memberInfo, object obj) => | ||
memberInfo.MemberType switch | ||
{ | ||
MemberTypes.Property => ((PropertyInfo)memberInfo).GetValue(obj), | ||
MemberTypes.Field => ((FieldInfo)memberInfo).GetValue(obj), | ||
_ => throw new NotImplementedException($"Getting value of {memberInfo.MemberType} is not implemented") | ||
}; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
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<TOwner>(this TOwner obj, | ||
Func<PrintingConfig<TOwner>, PrintingConfig<TOwner>> config) | ||
{ | ||
return config(ObjectPrinter.For<TOwner>()).PrintToString(obj); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System; | ||
using System.Globalization; | ||
|
||
namespace ObjectPrinting.Extensions | ||
{ | ||
public static class PrintingPropertyConfigExtensions | ||
{ | ||
public static PrintingConfig<TOwner> ToTrimmedLength<TOwner>( | ||
this PrintingPropertyConfig<TOwner, string> config, int maxLength) => | ||
config.To(x => x.Length <= maxLength ? x : x[..maxLength]); | ||
|
||
public static PrintingConfig<TOwner> To<TOwner, TPropType>( | ||
this PrintingPropertyConfig<TOwner, TPropType> config, CultureInfo culture) where TPropType : IFormattable | ||
{ | ||
return config.To(x => x.ToString(null, culture)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,139 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Linq.Expressions; | ||
using System.Reflection; | ||
using System.Text; | ||
using ObjectPrinting.Extensions; | ||
|
||
namespace ObjectPrinting | ||
{ | ||
public class PrintingConfig<TOwner> | ||
{ | ||
public string PrintToString(TOwner obj) | ||
private readonly HashSet<Type> finalTypes = new HashSet<Type> | ||
{ | ||
return PrintToString(obj, 0); | ||
typeof(int), typeof(double), typeof(float), | ||
typeof(bool), typeof(long), typeof(string), | ||
typeof(DateTime), typeof(TimeSpan), typeof(Guid) | ||
}; | ||
|
||
private readonly HashSet<MemberInfo> excludedMembers = new HashSet<MemberInfo>(); | ||
private readonly HashSet<Type> excludedTypes = new HashSet<Type>(); | ||
private readonly HashSet<object> serializedObjects = new HashSet<object>(); | ||
|
||
private readonly Dictionary<MemberInfo, Func<object, string>> memberSerializers = | ||
new Dictionary<MemberInfo, Func<object, string>>(); | ||
|
||
public string PrintToString(TOwner obj) => PrintToString(obj, 0); | ||
|
||
public PrintingConfig<TOwner> ExcludeProperty<TProperty>() | ||
{ | ||
excludedTypes.Add(typeof(TProperty)); | ||
return this; | ||
} | ||
|
||
public PrintingConfig<TOwner> ExcludeProperty<TProperty>(Expression<Func<TOwner, TProperty>> memberSelector) | ||
{ | ||
excludedMembers.Add(((MemberExpression)memberSelector.Body).Member); | ||
return this; | ||
} | ||
|
||
public PrintingPropertyConfig<TOwner, TProperty> ChangeSerializationFor<TProperty>() => | ||
new PrintingPropertyConfig<TOwner, TProperty>(this, memberSerializers, typeof(TProperty)); | ||
|
||
public PrintingPropertyConfig<TOwner, TPropType> ChangeSerializationFor<TPropType>( | ||
Expression<Func<TOwner, TPropType>> memberSelector) | ||
{ | ||
var body = (MemberExpression)memberSelector.Body; | ||
return new PrintingPropertyConfig<TOwner, TPropType>(this, memberSerializers, body.Member); | ||
} | ||
|
||
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())) | ||
{ | ||
if (memberSerializers.TryGetValue(obj.GetType(), out var serializer)) | ||
return serializer(obj) + Environment.NewLine; | ||
return obj + Environment.NewLine; | ||
} | ||
|
||
if (!serializedObjects.Add(obj)) | ||
return "Cycle, object was already serialized." + Environment.NewLine; | ||
|
||
var identation = new string('\t', nestingLevel + 1); | ||
return obj switch | ||
{ | ||
IList collection => SerializeCollection(collection, nestingLevel), | ||
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. Кажется, что проверять на список по интерфейсу |
||
IDictionary dictionary => SerializeDictionary(dictionary, nestingLevel), | ||
_ => SerializeObject(obj, nestingLevel) | ||
}; | ||
} | ||
|
||
private string SerializeCollection(IList collection, int nestingLevel) | ||
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. Давай вытащим конкретные кейсы сериализации в отдельный класс-утилиту для сериализации |
||
{ | ||
var sb = new StringBuilder(collection.GetType().Name + " {" + Environment.NewLine); | ||
foreach (var item in collection) | ||
{ | ||
sb.Append(new string('\t', nestingLevel + 1)); | ||
sb.Append(PrintToString(item, nestingLevel + 1)); | ||
} | ||
sb.Append(new string('\t', nestingLevel) + '}' + Environment.NewLine); | ||
return sb.ToString(); | ||
} | ||
|
||
private string SerializeDictionary(IDictionary dictionary, int nestingLevel) | ||
{ | ||
var sb = new StringBuilder(dictionary.GetType().Name + " {" + Environment.NewLine); | ||
foreach (var key in dictionary.Keys) | ||
{ | ||
sb.Append(new string('\t', nestingLevel + 1)); | ||
sb.Append(PrintToString(key, nestingLevel + 1).Trim() + " = "); | ||
sb.Append(PrintToString(dictionary[key], nestingLevel+ 1)); | ||
} | ||
sb.Append(new string('\t', nestingLevel) + '}' + Environment.NewLine); | ||
|
||
return sb.ToString(); | ||
} | ||
|
||
private string SerializeObject(object obj, int nestingLevel) | ||
{ | ||
var indent = new string('\t', nestingLevel + 1); | ||
var sb = new StringBuilder(); | ||
var type = obj.GetType(); | ||
sb.AppendLine(type.Name); | ||
foreach (var propertyInfo in type.GetProperties()) | ||
foreach (var memberInfo in type.GetMembers(BindingFlags.Public | BindingFlags.Instance) | ||
.Where(t => t.MemberType == MemberTypes.Field || t.MemberType == MemberTypes.Property) | ||
.Where(x => !IsMemberExcluded(x))) | ||
{ | ||
sb.Append(identation + propertyInfo.Name + " = " + | ||
PrintToString(propertyInfo.GetValue(obj), | ||
nestingLevel + 1)); | ||
sb.Append( | ||
indent + memberInfo.Name + " = " + | ||
SerializeMember(obj, memberInfo, nestingLevel + 1) | ||
); | ||
} | ||
|
||
return sb.ToString(); | ||
} | ||
|
||
private string SerializeMember(object obj, MemberInfo memberInfo, int nestingLevel) | ||
{ | ||
return TryGetCustomSerializer(memberInfo, out var serializer) | ||
? serializer.Invoke(memberInfo.GetValue(obj)) + Environment.NewLine | ||
: PrintToString(memberInfo.GetValue(obj), nestingLevel); | ||
} | ||
|
||
private bool TryGetCustomSerializer(MemberInfo memberInfo, out Func<object, string> serializer) | ||
{ | ||
return memberSerializers.TryGetValue(memberInfo, out serializer) || | ||
memberSerializers.TryGetValue(memberInfo.GetMemberType(), out serializer); | ||
} | ||
|
||
private bool IsMemberExcluded(MemberInfo memberInfo) | ||
{ | ||
return excludedMembers.Contains(memberInfo) || | ||
excludedTypes.Contains(memberInfo.GetMemberType()); | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Reflection; | ||
|
||
namespace ObjectPrinting | ||
{ | ||
public class PrintingPropertyConfig<TOwner, TProperty> | ||
{ | ||
private readonly MemberInfo memberInfo; | ||
private readonly PrintingConfig<TOwner> printingConfig; | ||
private readonly Dictionary<MemberInfo, Func<object, string>> serializers; | ||
|
||
public PrintingPropertyConfig(PrintingConfig<TOwner> printingConfig, | ||
Dictionary<MemberInfo, Func<object, string>> serializers, | ||
MemberInfo memberInfo) | ||
{ | ||
this.printingConfig = printingConfig; | ||
this.serializers = serializers; | ||
this.memberInfo = memberInfo; | ||
} | ||
|
||
public PrintingConfig<TOwner> To(Func<TProperty, string> serializeRule) | ||
{ | ||
serializers[memberInfo] = x => serializeRule((TProperty)x); | ||
return printingConfig; | ||
} | ||
} | ||
} |
This file was deleted.
This file was deleted.
This file was deleted.
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.
А как же остальные простые типы? Например, uint, decimal и тд?
На самом деле есть более простой способ узнать, является ли тип простым, не перечисляя все числовые вариации. Небольшая подсказка: посмотри в сторону Type