Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

C# - быстро склонировать несложный объект

2158  1 2 3 4 все
Murr патриот13.10.23 13:57
Murr
NEW 13.10.23 13:57 
в ответ alex445 12.10.23 22:55

чтобы сохранённый вариант был человекочитаемый

------

И какие проблемы?

Подставляешь нужный сериалайзер и получаешь что требуется.

#41 
Murr патриот13.10.23 14:03
Murr
NEW 13.10.23 14:03 
в ответ alex445 13.10.23 00:52

то столбцы всё равно неровными могут быть

-----

Какая хрень...

Дампишь дататабле с дополнением полей до полного и получаешь абсолютно ровненькие колонки...

#42 
Murr патриот13.10.23 14:11
Murr
NEW 13.10.23 14:11 
в ответ alex445 13.10.23 10:41

из всей нужной функциональности

-----

Из всей известной тебе функциональности.

Там вполне работает LINQ, кроме этого - фильтрация по SQL.


Тогда зачем мне вся эта инфраструктура датасетов, если поддерживать её сложнее, и редактировать быстро извне в простой сторонней программе типа Блокнота нельзя?

-----

Это ограничения твоих знаний...

#43 
alex445 коренной житель13.10.23 14:17
NEW 13.10.23 14:17 
в ответ Программист 13.10.23 11:41
Если тебе нужна лайт BD, то DataSet оптимальное решение. А еще DataSet можно подружить с твоим любимым EF и вообще кайф :D

Мне нужна ещё более лайт, чем датасеты - без связей между таблицами. Чем пачка List<T> или Dictionaty<T,T> не лайт ин-мемори ДБ без связей? Просто она не relational. И EF не нужен, т.к. всё и так типизировано. ))


Вопрос лишь в том, как хранить на диске. С датасетами - ок, можно писать-читать XML. Но и List<T> можно сериализовать в джейсон без проблем, если там POCO без связей.


Теперь другой вопрос - мне надо ещё и сериализовать граф объектов (состояние программы). Тут датасеты не нужны, а сераилазация снова в деле. Итого, для разных задач могу использовать лишь одну либу (например, для сериализации в джейсон), или разные либы (для сериализации в джейсон и для простейшей БД).

#44 
alex445 коренной житель13.10.23 14:19
NEW 13.10.23 14:19 
в ответ alex445 13.10.23 14:17, Последний раз изменено 13.10.23 14:26 (alex445)

Посмотрел в Unity 3d - вроде, System.Data.dll подключается. Ок, можно оставить на заметку.


Посмотрел best practices в других небольших игровых проектах - не юзают люди БД. Хранят всё в джейсоне или YAML, редко в XML. Потом всё грузят в память и читают из памяти как из хранилища (базы данных). Там сама идея, что зависимости тебе нужны лишь при работающей программе - ты грузишь объекты из БД и создаёшь связи между ними. А в самой БД связи не нужны. А если хочешь состояние со связями сохранить, то сериализуешь, а не в БД сохраняешь. Чтобы в БД сохранить состояние, это надо, чтобы все объекты состояния присутствовали в БД в виде таблиц со связями. А это зачастую не нужно.

#45 
AlexNek патриот13.10.23 17:59
AlexNek
NEW 13.10.23 17:59 
в ответ alex445 13.10.23 14:17
Вопрос лишь в том, как хранить на диске.


Опять не понимаю. А зачем вообще нужно сохранять на диске да и еще в удобочитаемом виде?

Откуда данные берутся вначале? Отчего нельзя данные редактировать сразу в проге?

#46 
alex445 коренной житель13.10.23 20:38
NEW 13.10.23 20:38 
в ответ AlexNek 13.10.23 17:59

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


В программе нет редактора данных. Отображение есть, а редактора нет. В теории можно сделать, но там стандартного грида из коробки нет, а эмулировать списком и по отдельности поля редактировать - муторно. В принципе, всё можно сделать, но мне проще не заморачиваться этим, а редактировать извне в каком-нибудь блокноте.

#47 
AlexNek патриот13.10.23 21:37
AlexNek
NEW 13.10.23 21:37 
в ответ alex445 13.10.23 20:38
Потом вручную буду редактировать джейсон - добавлять новые данные

А в чём разница добавлять или редактировать?


А что то типа этого чем не нравится?

https://github.com/mcw82/propertygrid

#48 
alex445 коренной житель14.10.23 00:58
NEW 14.10.23 00:58 
в ответ AlexNek 13.10.23 21:37, Последний раз изменено 14.10.23 01:06 (alex445)

Это для редактора, не для рантайма. Редактор в Юнити - это когда делаешь игру, а рантайм - когда её запускаешь.


Да в принципе много можно чего найти. Бесплатного и платного. При желании на Юнити можно сделать какой угодно датагрид с привязками и прочим. Ну будет сколько-то стоить - можно заплатить. Просто мне это сейчас не надо. Я хочу как можно быстрее и проще избавиться от рутины и делать то, что интересно. Проще добавить пару объектов в коде, сохранить, и потом раз в неделю добавлять ещё в качестве теста по паре объектов в текстовом файле, чем писать самому какой-то сложный контрол для редактирования в игре, или искать подобный уже готовый и его осваивать.


Если захочу не вручную, то можно что-то типа такого использовать.

#49 
AlexNek патриот14.10.23 14:31
AlexNek
NEW 14.10.23 14:31 
в ответ alex445 14.10.23 00:58

ааа, так для себя и юнити. Конечно, не нужен редактор. Консоль приложение для генерации файла вполне достаточно будет, думаю

#50 
alex445 коренной житель21.10.23 13:41
NEW 21.10.23 13:41 
в ответ alex445 08.10.23 19:54

Ну и конечно никаких свойств с неопределёнными типами, типа интерфейсов, object и прочего.

#51 
AlexNek патриот21.10.23 17:02
AlexNek
NEW 21.10.23 17:02 
в ответ alex445 21.10.23 13:41

но вот зачем клонирование нужно, так и не дошло смущ

Генерим всё что надо и усё....

#52 
alex445 коренной житель21.10.23 20:37
NEW 21.10.23 20:37 
в ответ AlexNek 21.10.23 17:02, Последний раз изменено 21.10.23 20:50 (alex445)

Я щас пытаюсь организовать в своих классах как я хотел. Как я раньше говорил - скормил объект сериализатору и всё - нет. Нужно придерживаться определённых правил при проектировании классов. Например, если конструкторов много разных, и есть по-умолчанию (без параметров), то нужно повесить атрибут сериализации на конструктор со всеми необходимыми параметрами, а если такого конструктора нет - создать его. Иначе при десериализации получишь объект с дефолтными полями (будет использован конструктор без параметров). Ну, это завязано на конкретный сериализатор. Можно через всякие дата контракты, но это муторнее.


Ещё раз, у меня такая идея. Есть импровизированная база данных в виде файликов (текстовые - джейсоны, csv или ещё что-то - неважно). Один файлик - одна таблица. Связей в базе данных между таблицами нет - это просто хранилище отдельных классов объектов. Скажем так, дефолтных параметров этих объектов. Там уникальные идентификаторы - текстовые поля (названия этих классов объектов). Например, две таблицы с идентификаторами "name"


таблица Characters:

className Warrior, attack 10, defence 5

className Archer, attack 5, defence 3

...


таблица Items:

className Knife, damage 2, price 400

className Sword, damage 5, price 1200

...


В базе данных может быть только один объект с уникальным именем класса, но в программе их может быть несколько - можно создать несколько Warrior, которые поначалу могут быть даже с одинаковыми параметрами, но потом могут начать различаться. Поэтому это уникальные Warriors, и им нужны свои идентификаторы - я выбрал инты, и затолкал их всех в словари , где T - тип объекта из файла (Warrior, Item, etc.). А в будущем нужно ещё добавить и понятные текстовые имена для персонажей однинаковых классов, например.


При запуске программы все таблицы из базы данных загружаются в виде обычных списков: List characterTable, List itemTable. Т.е. в них хранятся образцы объектов с дефолтными параметрами. И вот, чтобы создать уникальный объект из списка с образцами и добавить его в словарь, мне надо его склонировать. Т.е. я делаю так

var newCharacter = characterTable.FirstOrDefault(c => c.Name == name)

затем клонирую newCharacter через сериализацию-десериализацию, а потом приписываю newCharacter уникальный интовый идентификатор, и сохраняю его в словаре .


А потом эти уникальные объекты в словарях нужно ещё сохранять через сериализацию и потом восстанавливать их.


Т.е. сериализация служит для двух вещей, выделенных жирным: клонирование объектов и сохранение состояния программы. И классы, которые можно сериализовать, нужно специально проектировать. В принципе, ничего особенного, но порасставлять атрибуты придётся.


Вобщем, я эмулирую СУБД и ORM, только очень просто. Использовать настоящую СУБД нельзя, т.к. Юнити их не поддерживает, а заниматься установкой муторно. Все в небольших проектах делают это тупо в текстовых файлах, чтобы не заморачиваться, тем более что списки дефолтных объектов обычно небольшие, и применение для этого СУБД не несёт никакого преимущества. А ещё желательно иметь возможность редактировать эти списки в самом простом подручном редакторе (типа Блокнота). Вы же для СУБД тоже имеете специальную программу для редактирования - та же SQL Server Management Studio это нехилая такая программулина. А без неё будете в командной строке таблицы редактировать и выводить.

#53 
Срыв покровов Забанен до 7/7/25 16:05 патриот21.10.23 20:59
NEW 21.10.23 20:59 
в ответ alex445 21.10.23 20:37, Последний раз изменено 21.10.23 21:02 (Срыв покровов)

говнокод какой-то.
почему не сделать чот типа Repository или Factory, которая при инициализации запоминает, что Warrior‘а нужно создавать со свойствами attack 10, defence 5?

В Repository делаешь функцию T GetInstance<T>() where T : Character и все чистенько без дрочки с серей и десерей.

#54 
alex445 коренной житель21.10.23 21:01
NEW 21.10.23 21:01 
в ответ Срыв покровов 21.10.23 20:59, Последний раз изменено 21.10.23 21:13 (alex445)

Я так и делаю - у меня есть класс репы, который всё это и делает. А роль фабрики выполняет клонирующий метод.


Свойства attack 10, defence 5 надо где-то хранить, а ещё редактировать. Не в коде же? Поэтому вот во внешних файликах, эмулирующих таблицы.


Ещё раз, была бы легко доступна нормальная СУБД, я бы её использовал. Но в Юнити всё сделано, чтобы использовали их продукты и привязывались к их движку, а всё постороннее интегрируется сложно. Так все делают, не только они.


В принципе, подошли бы наверное мини СУБД из ссылок АлексНека, если весь движок это одна ДЛЛка. Но они там непонятно в каких файлах хранят данные. А мне нужно простые для редактирования.

#55 
Срыв покровов Забанен до 7/7/25 16:05 патриот21.10.23 21:04
NEW 21.10.23 21:04 
в ответ alex445 21.10.23 21:01

нифига ты не так делаешь.
у тебя список эталонных объектов и каждый раз ты берешь один и клонируешь его

#56 
AlexNek патриот21.10.23 21:04
AlexNek
NEW 21.10.23 21:04 
в ответ alex445 21.10.23 20:37

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

И процесс создания объекта назван "клонированием". Ну да ладно, можно и так посмотреть, хотя это должны быть два различных объекта.

И в сериализации когда то будет проблема обновления объекта.

#57 
Срыв покровов Забанен до 7/7/25 16:05 патриот21.10.23 21:07
NEW 21.10.23 21:07 
в ответ alex445 21.10.23 21:01

ну и еще если у тебя по условию задачи в файлике один хер каждый тип только один раз записан, то почему его свойства не прописывать в стандартном конструкторе класса?

Ты сначала объяснял по-другому, якобы тебе нужно инициировать много перосонажей одного типа.

#58 
alex445 коренной житель21.10.23 21:19
NEW 21.10.23 21:19 
в ответ Срыв покровов 21.10.23 20:59
В Repository делаешь функцию T GetInstance<T>() where T : Character и все чистенько без дрочки с серей и десерей.

Ну а сами-то функции что делают? Весь "говнокод" как раз в них и спрятан будет. У меня тоже самое.

#59 
alex445 коренной житель21.10.23 21:20
NEW 21.10.23 21:20 
в ответ Срыв покровов 21.10.23 21:04, Последний раз изменено 21.10.23 21:21 (alex445)
нифига ты не так делаешь.
у тебя список эталонных объектов и каждый раз ты берешь один и клонируешь его

А какая разница, как ваш GetInstance создаёт этот инстанс? Хочу и клонирую - я же расписал, как, зачем и почему так делаю. Весь "говнокод" за этим методом спрятан. Будет СУБД, поменяю на СУБД, а метод останется тем же. Всё по фен-шую, но пока без СУБД.

#60 
1 2 3 4 все