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

Зиновьева Милана #216

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
58 changes: 30 additions & 28 deletions ObjectPrintingHomework/PrintingConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ public class PrintingConfig<TOwner>
private readonly Dictionary<Type, Func<object, string>> typeSerializers = [];
private readonly Dictionary<string, Func<object, string>> propertySerializers = [];
private readonly Dictionary<Type, CultureInfo> typeCultures = [];
private readonly Dictionary<string, int> stringPropertyLengths = [];
private readonly HashSet<object> processedObjects = new HashSet<object>();
private readonly Dictionary<string, Tuple<int, int>> stringPropertyLengths = [];
private readonly HashSet<object> processedObjects = [];

public string PrintToString(TOwner obj)
{
Expand All @@ -25,8 +25,9 @@ public PrintingConfig<TOwner> Excluding<TPropType>()
}
public PrintingConfig<TOwner> Excluding<TPropType>(Expression<Func<TOwner, TPropType>> memberSelector)
{
if (memberSelector.Body is MemberExpression memberExpression)
excludedProperties.Add(memberExpression.Member.Name);
if (memberSelector.Body is not MemberExpression memberExpression)
throw new ArgumentException("Needed MemberExpression");
excludedProperties.Add(memberExpression.Member.Name);
return this;
}

Expand All @@ -44,52 +45,53 @@ public PropertyPrintingConfig<TOwner, TPropType> Printing<TPropType>(Expression<
private string PrintToString(object obj, int nestingLevel)
{
if (obj == null)
return "null" + Environment.NewLine;
return string.Empty;

var type = obj.GetType();

if (processedObjects.Contains(obj))
return "Circular Reference" + Environment.NewLine;
processedObjects.Add(obj);
return "Circular Reference";

if (excludedTypes.Contains(type))
return string.Empty;

This comment was marked as resolved.

This comment was marked as resolved.

processedObjects.Add(obj);

if (typeSerializers.ContainsKey(type))
return typeSerializers[type](obj) + Environment.NewLine;
if (typeSerializers.TryGetValue(type, out var serializer))
return serializer(obj);

if (typeCultures.TryGetValue(type, out var culture) && obj is IFormattable formattable)
return formattable.ToString(null, culture) + Environment.NewLine;
return formattable.ToString(null, culture);

var finalTypes = new[]
{
typeof(int), typeof(double), typeof(float), typeof(string),
typeof(DateTime), typeof(TimeSpan)
};
if (finalTypes.Contains(obj.GetType()))
return obj + Environment.NewLine;
if (type.IsSerializable && type.Namespace.StartsWith("System"))
return obj.ToString();

var identation = new string('\t', nestingLevel + 1);
var indentation = new string('\t', nestingLevel + 1);
var sb = new StringBuilder();
sb.AppendLine(type.Name);

foreach (var propertyInfo in type.GetProperties())
{
var propertyType = propertyInfo.PropertyType;
var propertyName = propertyInfo.Name;
var propertyValue = propertyInfo.GetValue(obj);

if (propertySerializers.ContainsKey(propertyName))
return propertySerializers[propertyName](propertyValue) + Environment.NewLine;
if (propertySerializers.TryGetValue(propertyName, out var propertySerializer))
{
sb.AppendLine(propertySerializer(propertyValue));
continue;
}

if (propertyValue is string stringValue && stringPropertyLengths.TryGetValue(propertyInfo.Name, out var maxLength))
propertyValue = stringValue[..Math.Min(maxLength, stringValue.Length)];
if (propertyValue is string stringValue && stringPropertyLengths.TryGetValue(propertyName, out var length))
propertyValue = stringValue.Substring(Math.Min(length.Item1, stringValue.Length))[..Math.Min(length.Item2, stringValue.Length)];

if (excludedTypes.Contains(propertyType) || excludedProperties.Contains(propertyName))
continue;
sb.Append(identation + propertyName + " = " +
PrintToString(propertyValue,
nestingLevel + 1));

sb.Append(indentation + propertyName + " = ");
sb.AppendLine(PrintToString(propertyValue, nestingLevel + 1));
}
return sb.ToString().Trim();

return sb.ToString();
}

public void AddTypeSerializer<TPropType>(Func<TPropType, string> serializer)
Expand All @@ -107,8 +109,8 @@ public void SetCulture<TPropType>(CultureInfo culture)
typeCultures[typeof(TPropType)] = culture;
}

public void SetStringPropertyLength(string propertyName, int maxLength)
public void SetStringPropertyLength(string propertyName, int startIndex, int maxLength)
{
stringPropertyLengths[propertyName] = maxLength;
stringPropertyLengths[propertyName] = new Tuple<int, int>(startIndex, maxLength);
}
}
4 changes: 2 additions & 2 deletions ObjectPrintingHomework/PropertyConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ public PrintingConfig<TOwner> Using(Func<TPropType, CultureInfo> culture)
return parentConfig;
}

public PrintingConfig<TOwner> TrimmedToLength(int maxLength)
public PrintingConfig<TOwner> TrimmedToLength(int startIndex, int maxLength)
{
if (typeof(TPropType) != typeof(string))
throw new InvalidOperationException("Trimming is only supported for string properties");

if (propertyName == null)
throw new InvalidOperationException("Property name must be specified for trimming");

parentConfig.SetStringPropertyLength(propertyName, maxLength);
parentConfig.SetStringPropertyLength(propertyName, startIndex, maxLength);
return parentConfig;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public void Demo()
//4. Настроить сериализацию конкретного свойства
.Printing<double>(p => p.Height).Using(i => new CultureInfo("ar-EG"))
//5. Настроить обрезание строковых свойств (метод должен быть виден только для строковых свойств)
.Printing(p => p.Name).TrimmedToLength(10)
.Printing(p => p.Name).TrimmedToLength(0, 10)
//6. Исключить из сериализации конкретного свойства
.Excluding(p => p.Age);

Expand Down
21 changes: 17 additions & 4 deletions TestsObjectPrinting/TestsObjectPrintingHomework.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public void TestAllExcludingTypes()
.Excluding<string>().Excluding<int>().Excluding<double>().Excluding<Guid>().Excluding<DateTime>().Excluding<Person[]>()
.PrintToString(person);

result.Should().Be(excepted);
result.Trim().Should().Be(excepted);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

напрягают эти тримы. Теперь понял зачем ты везде тыкала newLine. Ну ладно, пусть будет перенос у пустого объекта

}

[Test]
Expand Down Expand Up @@ -64,7 +64,7 @@ public void TestExcludingAllProperties()
.Excluding(p => p.Id).Excluding(p => p.Name).Excluding(p => p.Surname).Excluding(p => p.DateBirth).Excluding<Person[]>()
.PrintToString(person);

result.Should().Be(excepted);
result.Trim().Should().Be(excepted);
}

[Test]
Expand Down Expand Up @@ -129,7 +129,19 @@ public void TestTrimmingSurname()
const string unexcepted = "Zinovieva";
const string excepted = "Zin";
var result = ObjectPrinter.For<Person>()
.Printing<string>(p => p.Surname).TrimmedToLength(3)
.Printing<string>(p => p.Surname).TrimmedToLength(0, 3)
.PrintToString(person);

result.Should().NotContain(unexcepted).And.Contain(excepted);
}

[Test]
public void TestTrimmingSurnameInMiddle()
{
const string unexcepted = "Zinovieva";
const string excepted = "inov";
var result = ObjectPrinter.For<Person>()
.Printing<string>(p => p.Surname).TrimmedToLength(1, 4)
.PrintToString(person);

result.Should().NotContain(unexcepted).And.Contain(excepted);
Expand All @@ -140,12 +152,13 @@ public void TestExceptionForTrimming()
{
Action action = () => ObjectPrinter.For<Person>()
.Printing<int>(p => p.Age)
.TrimmedToLength(3);
.TrimmedToLength(0, 3);

action.Should().Throw<InvalidOperationException>()
.WithMessage("Trimming is only supported for string properties");
}


[Test]
public void Work_WhenReferenceCycles()
{
Expand Down