C# - быстро склонировать несложный объект
из всей нужной функциональности
-----
Из всей известной тебе функциональности.
Там вполне работает LINQ, кроме этого - фильтрация по SQL.
Тогда зачем мне вся эта инфраструктура датасетов, если поддерживать её сложнее, и редактировать быстро извне в простой сторонней программе типа Блокнота нельзя?
-----
Это ограничения твоих знаний...
Если тебе нужна лайт BD, то DataSet оптимальное решение. А еще DataSet можно подружить с твоим любимым EF и вообще кайф :D
Мне нужна ещё более лайт, чем датасеты - без связей между таблицами. Чем пачка List<T> или Dictionaty<T,T> не лайт ин-мемори ДБ без связей? Просто она не relational. И EF не нужен, т.к. всё и так типизировано. ))
Вопрос лишь в том, как хранить на диске. С датасетами - ок, можно писать-читать XML. Но и List<T> можно сериализовать в джейсон без проблем, если там POCO без связей.
Теперь другой вопрос - мне надо ещё и сериализовать граф объектов (состояние программы). Тут датасеты не нужны, а сераилазация снова в деле. Итого, для разных задач могу использовать лишь одну либу (например, для сериализации в джейсон), или разные либы (для сериализации в джейсон и для простейшей БД).
Посмотрел в Unity 3d - вроде, System.Data.dll подключается. Ок, можно оставить на заметку.
Посмотрел best practices в других небольших игровых проектах - не юзают люди БД. Хранят всё в джейсоне или YAML, редко в XML. Потом всё грузят в память и читают из памяти как из хранилища (базы данных). Там сама идея, что зависимости тебе нужны лишь при работающей программе - ты грузишь объекты из БД и создаёшь связи между ними. А в самой БД связи не нужны. А если хочешь состояние со связями сохранить, то сериализуешь, а не в БД сохраняешь. Чтобы в БД сохранить состояние, это надо, чтобы все объекты состояния присутствовали в БД в виде таблиц со связями. А это зачастую не нужно.
Первое данное я создам в коде и сериализирую на диск в виде джейсона скорее всего. Потом вручную буду редактировать джейсон - добавлять новые данные. Там же просто массив будет, так элементы массива копипастой добавляешь и редактируешь.
В программе нет редактора данных. Отображение есть, а редактора нет. В теории можно сделать, но там стандартного грида из коробки нет, а эмулировать списком и по отдельности поля редактировать - муторно. В принципе, всё можно сделать, но мне проще не заморачиваться этим, а редактировать извне в каком-нибудь блокноте.
Потом вручную буду редактировать джейсон - добавлять новые данные
А в чём разница добавлять или редактировать?
А что то типа этого чем не нравится?
Это для редактора, не для рантайма. Редактор в Юнити - это когда делаешь игру, а рантайм - когда её запускаешь.
Да в принципе много можно чего найти. Бесплатного и платного. При желании на Юнити можно сделать какой угодно датагрид с привязками и прочим. Ну будет сколько-то стоить - можно заплатить. Просто мне это сейчас не надо. Я хочу как можно быстрее и проще избавиться от рутины и делать то, что интересно. Проще добавить пару объектов в коде, сохранить, и потом раз в неделю добавлять ещё в качестве теста по паре объектов в текстовом файле, чем писать самому какой-то сложный контрол для редактирования в игре, или искать подобный уже готовый и его осваивать.
Если захочу не вручную, то можно что-то типа такого использовать.
Я щас пытаюсь организовать в своих классах как я хотел. Как я раньше говорил - скормил объект сериализатору и всё - нет. Нужно придерживаться определённых правил при проектировании классов. Например, если конструкторов много разных, и есть по-умолчанию (без параметров), то нужно повесить атрибут сериализации на конструктор со всеми необходимыми параметрами, а если такого конструктора нет - создать его. Иначе при десериализации получишь объект с дефолтными полями (будет использован конструктор без параметров). Ну, это завязано на конкретный сериализатор. Можно через всякие дата контракты, но это муторнее.
Ещё раз, у меня такая идея. Есть импровизированная база данных в виде файликов (текстовые - джейсоны, 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 это нехилая такая программулина. А без неё будете в командной строке таблицы редактировать и выводить.
говнокод какой-то.
почему не сделать чот типа Repository или Factory, которая при инициализации запоминает, что Warrior‘а нужно создавать со свойствами attack 10, defence 5?
В Repository делаешь функцию T GetInstance<T>() where T : Character и все чистенько без дрочки с серей и десерей.
Я так и делаю - у меня есть класс репы, который всё это и делает. А роль фабрики выполняет клонирующий метод.
Свойства attack 10, defence 5 надо где-то хранить, а ещё редактировать. Не в коде же? Поэтому вот во внешних файликах, эмулирующих таблицы.
Ещё раз, была бы легко доступна нормальная СУБД, я бы её использовал. Но в Юнити всё сделано, чтобы использовали их продукты и привязывались к их движку, а всё постороннее интегрируется сложно. Так все делают, не только они.
В принципе, подошли бы наверное мини СУБД из ссылок АлексНека, если весь движок это одна ДЛЛка. Но они там непонятно в каких файлах хранят данные. А мне нужно простые для редактирования.
Ага, в проге есть объекты, которым нужно сохранять состояние и создавать их на основе начальных данных.
И процесс создания объекта назван "клонированием". Ну да ладно, можно и так посмотреть, хотя это должны быть два различных объекта.
И в сериализации когда то будет проблема обновления объекта.
ну и еще если у тебя по условию задачи в файлике один хер каждый тип только один раз записан, то почему его свойства не прописывать в стандартном конструкторе класса?
Ты сначала объяснял по-другому, якобы тебе нужно инициировать много перосонажей одного типа.
нифига ты не так делаешь.
у тебя список эталонных объектов и каждый раз ты берешь один и клонируешь его
А какая разница, как ваш GetInstance создаёт этот инстанс? Хочу и клонирую - я же расписал, как, зачем и почему так делаю. Весь "говнокод" за этим методом спрятан. Будет СУБД, поменяю на СУБД, а метод останется тем же. Всё по фен-шую, но пока без СУБД.