Skip to content

HomeworkV2#250

Open
Balashov2004 wants to merge 13 commits intokontur-courses:masterfrom
Balashov2004:homework
Open

HomeworkV2#250
Balashov2004 wants to merge 13 commits intokontur-courses:masterfrom
Balashov2004:homework

Conversation

@Balashov2004
Copy link
Copy Markdown

No description provided.

using System;
using System.Collections.Generic;

namespace ObjectPrinting;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

namespace поломан
папку с большой буквы

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

namespace ObjectPrinting.Interface;

Comment on lines +10 to +15
public HashSet<Type> ExcludedTypes { get; } = new();
public HashSet<string> ExcludedProperties { get; } = new();

public Dictionary<Type, Func<object, string>> TypeSerializers { get; } = new();
public Dictionary<string, Func<object, string>> PropertySerializers { get; } = new();
public Dictionary<string, int> TrimLengths { get; } = new();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Все это отображается в интелисенсе, что будет мешать изучению сервиса через fluent подход.
Плюсом, я могу в обход методов добавить в твои коллекции что угодно

Copy link
Copy Markdown
Author

@Balashov2004 Balashov2004 Nov 21, 2025

Choose a reason for hiding this comment

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

не понял
они же должны вызываться то есть не могут быть private


public PrintingConfig<TOwner> Excluding<TProp>(Expression<Func<TOwner, TProp>> selector)
{
var name = ((MemberExpression)selector.Body).Member.Name;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

По условиям задачи - "Исключение из сериализации конкретного свойства/поля".
А значит это исключение не должно влиять на другие типы с таким же названием поля. У тебя сейчас влияет

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Под эту ситуацию нужны также тесты


namespace ObjectPrinting;

public interface IPrintingConfigInternal
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Для чего нам в целом интерфейс?

Comment thread ObjectPrinting/PrintingConfig.cs Outdated
Comment on lines +31 to +32
public TypePrintingConfig<TOwner, TProp> Printing<TProp>()
=> new TypePrintingConfig<TOwner, TProp>(this);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

unused

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

убрал

Comment thread ObjectPrinting/ObjectTraversal.cs Outdated

namespace ObjectPrinting
{
public static class ObjectTraversal
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Давай назовем более понятно

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Не очень понимаю смысл статичности в этом случае

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

исправил

Comment thread ObjectPrinting/ObjectTraversal.cs Outdated
Comment on lines +51 to +74
foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.GetIndexParameters().Length == 0))
{
if (config.ExcludedTypes.Contains(property.PropertyType)) continue;
if (config.ExcludedProperties.Contains(property.Name)) continue;

var value = property.GetValue(obj);
string printed = PrintMember(property.Name, value, property.PropertyType,
config, level + 1, visited);

sbObj.Append(indentObj + "\t" + printed);
}

foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance))
{
if (config.ExcludedTypes.Contains(field.FieldType)) continue;
if (config.ExcludedProperties.Contains(field.Name)) continue;

var value = field.GetValue(obj);
string printed = PrintMember(field.Name, value, field.FieldType,
config, level + 1, visited);

sbObj.Append(indentObj + "\t" + printed);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

DRY

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Разбил

Comment thread ObjectPrinting/ObjectTraversal.cs Outdated
Comment on lines +87 to +105
if (config.PropertySerializers.TryGetValue(memberName, out var serializer))
{
string val = serializer(value);
return memberName + " = " + val + "\n";
}

if (config.TypeSerializers.TryGetValue(memberType, out var typeSerializer))
{
string val = typeSerializer(value);
return memberName + " = " + val + "\n";
}

if (config.TrimLengths.TryGetValue(memberName, out var maxLen) && value is string s)
{
if (s.Length > maxLen)
s = s.Substring(0, maxLen);

return memberName + " = " + s + "\n";
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Потенциальное исключение, пример на пикрил
image

Comment thread ObjectPrinting/ObjectTraversal.cs Outdated
Comment on lines +87 to +97
if (config.PropertySerializers.TryGetValue(memberName, out var serializer))
{
string val = serializer(value);
return memberName + " = " + val + "\n";
}

if (config.TypeSerializers.TryGetValue(memberType, out var typeSerializer))
{
string val = typeSerializer(value);
return memberName + " = " + val + "\n";
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

DRY. Вызвали функцию -> сериализовали

Comment thread ObjectPrinting/ObjectTraversal.cs Outdated
return sbObj.ToString();
}

private static string PrintMember(
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Обрезание строки никогда не будет работать, если задана кастомная обработка строчки.

В случае с полем - более приоритетная обработка поля, тут ок.
Но вот трим и обработка строки - на одном уровне, это буквально синтактическое упрощение.


public class TypeHelper
{
public static bool IsSimpleType(Type type)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Лучше переделать в Extensions и вызывать прямо из типа.

typeof(...).IsSimpleType

Comment on lines +9 to +16
if (type.IsPrimitive) return true;
if (type == typeof(string)) return true;
if (type == typeof(decimal)) return true;
if (type == typeof(DateTime)) return true;
if (type == typeof(TimeSpan)) return true;
if (type.IsEnum) return true;

return false;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

return type.IsPrimitive ||
type == typeof(string) || ...

public class ReferenceEqualityComparer : IEqualityComparer<Object>
{
public new bool Equals(object x, object y) => ReferenceEquals(x, y);
public int GetHashCode(object obj) => RuntimeHelpers.GetHashCode(obj);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

А obj.GetHashCode почему не подошел?


namespace ObjectPrinting;

public class ReferenceEqualityComparer : IEqualityComparer<Object>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Comment on lines +46 to +65
foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (property.GetIndexParameters().Length > 0) continue;
if (config.ExcludedTypes.Contains(property.PropertyType)) continue;
if (config.ExcludedProperties.Contains(property.Name)) continue;

var value = property.GetValue(obj);
sb.Append(indent + "\t" +
memberPrinter.PrintMember(property.Name, value, property.PropertyType, config, level + 1, visited, this));
}

foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance))
{
if (config.ExcludedTypes.Contains(field.FieldType)) continue;
if (config.ExcludedProperties.Contains(field.Name)) continue;

var value = field.GetValue(obj);
sb.Append(indent + "\t" +
memberPrinter.PrintMember(field.Name, value, field.FieldType, config, level + 1, visited, this));
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

DRY так и осталось

Comment on lines +8 to +14
HashSet<Type> ExcludedTypes { get; }
HashSet<string> ExcludedProperties { get; }

Dictionary<Type, Func<object, string>> TypeSerializers { get; }
Dictionary<string, Func<object, string>> PropertySerializers { get; }
Dictionary<string, int> TrimLengths { get; }
public int? GlobalStringTrimLength { get; }
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Я продолжаю мочь добавлять элементы напрямую в коллекции.

Зачем мне мучиться с контекстами, валидациями и т.д, если я могу просто написать TrimLength["Name"]=0

Comment on lines +21 to +25
public PrintingConfig<TOwner> TrimStringsGlobal(int maxLength)
{
GlobalStringTrimLength = maxLength;
return this;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

В целом так сделать можно. Но мы на этом уровне не работаем с конкретными типами.

Лучше, чтобы было типа такого: config.Printing().Trimmed(5)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Сделать это можно так:

public static PrintingConfig Trimmed(
this MemberPrintingConfig<TOwner, string> propConfig, int maxLen)

Comment on lines +24 to +29
public IStringMemberConfig<TOwner> AsString()
{
return typeof(TProp) == typeof(string)
? new StringMemberConfig<TOwner>(config, memberName)
: throw new InvalidOperationException("Property is not string");
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

С точки зрения интерфейса выглядит ультра странно. Я и так передал конкретное поле с конкретным типом. Но чтобы появилась пачка методов, я должен еще раз сказать тип.

Допустим, у нас появятся для других типов кастомные методы. Мы также будем дописывать AsGuid, AsEnum, AsInt?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Плюсом, у нас возможно исключение. Что вообще весь пользовательский опыт рушит

Comment on lines +18 to +22
public PrintingConfig<TOwner> Using(Func<TProp, string> serializer)
{
config.PropertySerializers[memberName] = obj => serializer((TProp)obj);
return config;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

unused

Comment on lines +21 to +30
public PrintingConfig<TOwner> Using(CultureInfo culture)
{
if (!typeof(IFormattable).IsAssignableFrom(typeof(TProp)))
throw new InvalidOperationException("Culture can be applied only to IFormattable");

config.TypeSerializers[typeof(TProp)] =
o => ((IFormattable)o).ToString(null, culture);

return config;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

По итогу остается, что я могу вызвать культуру даже к типам, которые культуры не имеют.
А вдобавок я получу исключение

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants