Опт. решение для разделения объектов данных от чтения/записи и отображения
Итак есть объект данных. Этот объект читается в отдельном проекте и выдается наружу для показа и редактирования. Выданный объект не должен иметь никаких видимых методов для записи и чтения.
Внутренний проект для чтения/записи должен конечно иметь функции чтения и записи объекта. Объектов довольно много так что расход памяти и скорость играют роль.
Чисто с отдельными простыми объектами решений может быть много, а вот когда объекты наследуются, да и еще динамически создаются с различными типами данных, когда нет даже возможности общий класс сделать, то удобного решения пока не вижу.
Наиболее удобно иметь в классе данных public virtual Read/Write(Stream s) и public virtual IEditor GetEditor(). Тогда и комбинируй как хошь и изменения удобно делать. Но всё вместе, что с одной стороны хорошо, а с другой плохо.Вот как бы всё разделить, но чтобы осталось удобно изменения делать?
Выданный объект не должен иметь никаких видимых методов для записи и чтения.
Вот как бы всё разделить, но чтобы осталось удобно изменения делать?
-----
Пример тебе дан в виде ISerializable & [Serializable]
Но из постановки задачи Я пока не вижу когда тебе надо связать Реад/Врите() с фактическими объектами.
Мне, например, уже не хочется иметь внутренние Реад/Врите - они хорошо, но уже никак не достаточно.
Хочется иметь один более/менее стандартизованный вызов, но совершенно дифференцированный результат.
Пример - есть производный от ДатаРов объект - хочется иметь ИнсертСтреам, ДелетеСтреам, ХмлОУТ/ИН, БинОут/ИН и т.п.
когда нет даже возможности общий класс сделать
-----
В .Нет всегда есть общий класс. Там где его нету - можно ввести принудительно...
Я пока не вижу когда тебе надо связать Реад/Врите() с фактическими объектами
А разве это имеет какое то значение?
В конкретном случае, данные находятся в двоичном формате в файле на диске.
Нужно прочитать и отобразить данный файл. Внутри списки различных объектов. От bool,int ,string до Dictionary и более сложных объектов.
В .Нет всегда есть общий класс.
А какой мне смысл от объекта? Ведь каждый объект данных имеет еще дополнительные поля.
А какой мне смысл от объекта?
-----
??? - Ну либо ты имеешь возможность написать Реад(объект)/Врите(объект) и внутрь запихать какой-то общий диспетчер, либо надо писать под каждую бранчь отдельно...
Наличие и количество производных типов роли не играет. Ролю играет количество различных базовых типов. В .Нет он один - достаточно написать одну пару методоv.
А разве это имеет какое то значение?
-----
Для меня - уже имеет - мне надо заменить результат трансляции Т4 шаблона.
Билли слепил нечто, в чем вывод размазан по коду и нет вариантов его заменить.
Поменять объект Я могу - там не шибко сложно - а вот слепить нужный выход - пока не получается и без поздней привязки - не получится...
Ну либо ты имеешь возможность написать Реад(объект)/Врите(объект)
Даже такой возможности не вижу
Нужно то преобразовать вначале в конкретный тип. А как быть с иерархией классов?
Ну например, сейчас я выдаю наверх только интерфейсы, все классы внутри реад/Врите. А вот куда девать редакторы вьюверы? Они то должны быть привязаны к конкретной имплементации.
Даже такой возможности не вижу
-----
А что мешает? Тип - есть, написать метод с параметром типа - можно...
Они то должны быть привязаны к конкретной имплементации.
-----
Фабрика или фабричный метод?
В основном вопрос будет - когда именно компиляется имплементация - в общем построении проекта или позднее, в ран-тайме...
Если первое - нужно определение типa.
Если второе - нужна атрибутика...
Я не совсем понял твою проблему...
Наиболее удобно иметь в классе данных public virtual Read/Write(Stream s) и public virtual IEditor GetEditor(). Тогда и комбинируй как хошь и изменения удобно делать.
Ну так и сделаешь 2 интерфейса:
public interface IReadWrite { void Read (string path); void Write (Stream s); } public interface IEditor { IEditor Editor {get;} }
Ну и дальше имплементируешь эти 2 интерфейса для каждого объекта данных.
Передаешь, естественно, не объекты данных, а один или другой интерфейс.
Чтобы не было доступа к этим методам, имплементируешь эти интервейсы explicitly :)
Ну так и сделаешь 2 интерфейса:
-----
Насколько Я понял - он как раз хочет "имплементацию" не в составе класса, а вообще в другой либе.
И... это... интерфейс у тебя проблемный - либо работаем с потоками, либо с именами файлов. Смешанное - оно тяжко... тяжелее только недописанное...
хочет "имплементацию" не в составе класса, а вообще в другой либе.
И это тоже. При чтении нужно пользоваться старой плюсовой либой а там столько "лишних" ссылок.
Ну и данные нужны сейчас для WPF, завтра Winforms или Console.
Вот интересный пример:
Из Winforms есть запросы к 32 битной С++ Манажед+анманагед либе чтения данных - всё работает, все тоже самое повторяем для WPF, работает пока данные не цепляются к биндингу на форму. Как цепляются - сразу вылетает "повреждение памяти" в плюсах.
Есть подозрение, что биндинг работает исключительно в 64 битном режиме. Потому как прога пересобиралась и в 32 битном режиме.
Вытаскивать всё самому из объекта довольно долго. Да и структура объекта довольно сложная
-----
А как ты вообще хотел?
Либо ты работаешь с объектом, либо строишь какие-то метаданные на базе объекта и работаешь с ними.
Во втором случае у тебя все сложнее, объемнее, но более управляемо при сторонних редакторах...
И как мне эти интерфейсы воткнуть в редактор? Которому надо что то типа "ColumnAbc = item.Length". Вытаскивать всё самому из объекта довольно долго. Да и структура объекта довольно сложная
Так в чем проблема-то?
public interface IReadWrite { void Read(Stream s); void Write(Stream s); } public interface IEditor { string Name { get; } int Length { get; } IEnumerable<IEditor> SubItems { get; } bool IsAvailable { get; set; } } public class SomeObject : IReadWrite, IEditor { private string _name = string.Empty; private List<SomeObject> _subObjects = new List<SomeObject>(); private bool _isAvailable = false; void IReadWrite.Read(Stream s) { ... } void IReadWrite.Write(Stream s) { ... } string IEditor.Name { get { return _name; } } int IEditor.Length { get { return _subObjects.Count; } } IEnumerable<IEditor> IEditor.SubItems { get { return _subObjects; } } bool IEditor.IsAvailable { get { return _isAvailable; } set { _isAvailable = value; } } } public class SomeEditor { public void Show(IEditor editor) { ColumnName = editor.Name; ColumnLength = editor.Length; CheckBoxAvailable.Checked = editor.IsAvailable; ListSubitens.AddRange(editor.SubItems); } } public class ReaderObj { public void Read(IReadWrite obj) { Stream s = // get stream obj.Read(s); } } public class Processing { public void DoWork(ReaderObj reader, SomeEditor editor) { SomeObject obj = new SomeObject(); reader.Read(obj); editor.Show(obj); } }
Очевидно, что класс ReaderObj может быть в любой сборке, также как и SomeEditor. При этом у объекта SomeObject нет никаких видимых полей. Более того, ни ReaderObj, ни SomeEditor вообще ничего не знают ни про какие объекты.
Не понимаю, какие тут могут быть трудности? Или ты в лучших традициях Murr'а утаил какие-то детали? :D
Так в чем проблема-то?
-----
Насколько Я понимаю - минимум две проблемы:
- void IReadWrite.Read(Stream s) & void IReadWrite.Write(Stream s) должны быть имплементированы там, где никто не знает об class SomeObject
- запрошена не имплементация ИЕдитор в классе, а наличие метода ГетЕдитор, который возвращает лежащий непонятно где редактор, умеющий работать с объектом, но не знающий фактический тип объекта...
void IReadWrite.Read(Stream s) & void IReadWrite.Write(Stream s) должны быть имплементированы там, где никто не знает об class SomeObject
Это делается еще одним уровнем абстракции. При этом вариантов два:
1) сделать универсальный интерфейс для SomeObject, которым можно было бы абстрагироваться от имен. Например такой:
public interface IDataContent { object this [string propertyName] { get; set; } }
SomeObject должен имплементировать этот интерфейс и именно его передавать ридеру.
2) сделать аналогичную абстракцию для ридера. Так что SomeObject будет получать этот интерфейс при чтении (типа такого: void IReadWrite.Read(IDataContent data)).
запрошена не имплементация ИЕдитор в классе, а наличие метода ГетЕдитор, который возвращает лежащий непонятно где редактор, умеющий работать с объектом, но не знающий фактический тип объекта...
Ну значит где-то должен быть метод, который знает и сам объект и редактор. И тут опять два варианта:
1) этот метод вызывается до того, как создается объект с данными. в этом случае интерфейс IEditor можно передать в конструктор.
2) этот метод можно вызвать непосредственно из геттера.
А вообще, стрелять себе в ногу и потом придумывать решения для элементарных задач - это, судя по всему, местная забава :D
должен имплементировать этот интерфейс
-----
Там, наверху, написано пожелание удобства. В данном варианте - неудобно.
Дальше будет либо медленно - рефлектионом через объект, либо относительно быстро - по метаданным.
стрелять себе в ногу и потом придумывать решения для элементарных задач
-----
Ээээ...
помнится, был файловый ввод/вывод... вполне себе элементарное решение...
потом файловый ИО заменили потоковым... вполне себе элементарное решение...
вроде как потоковый заменили сериализатором... таки тоже вполне элементарное решение...
И чаво это народ себе в ноги постоянно стреляет?
И - да - таки тоже хочу иметь удобное и красивое решение... простая сериализация уже не устраивает...
Там, наверху, написано пожелание удобства. В данном варианте - неудобно.
там, наверху, написано следующее:
Наиболее удобно иметь в классе данных public virtual Read/Write(Stream s)
т.е. Read и Write - часть объекта данных, т.е. объект данных сам себя считывает из потока или записывает в поток.
С чего ты взял, что чтение должно происходить где-то в другом месте, где никто ничего не знает об объекте денных мне лично не понятно.
помнится, был файловый ввод/вывод... вполне себе элементарное решение...
да, но узкой специализации
потом файловый ИО заменили потоковым... вполне себе элементарное решение...
только не заменили, а объеденили считывание любых данных одной абстракцией.
вроде как потоковый заменили сериализатором... таки тоже вполне элементарное решение...
сериализатор решает также узкую задачу.
И чаво это народ себе в ноги постоянно стреляет?
Не стреляет. Народ решает наиболее часто встречающиеся проблемы максимально абстрагировавшись от предметной области.
И - да - таки тоже хочу иметь удобное и красивое решение... простая сериализация уже не устраивает...
Суда про всему, ты не знаешь чего ты хочешь. И не знаешь, чем не устраивает тебя сериализация :D
Итак есть объект данных. Этот объект читается в отдельном проекте и выдается наружу для показа и редактирования. Выданный объект не должен иметь никаких видимых методов для записи и чтения. Внутренний проект для чтения/записи должен конечно иметь функции чтения и записи объекта. Объектов довольно много так что расход памяти и скорость играют роль. Чисто с отдельными простыми объектами решений может быть много, а вот когда объекты наследуются, да и еще динамически создаются с различными типами данных, когда нет даже возможности общий класс сделать, то удобного решения пока не вижу. Наиболее удобно иметь в классе данных public virtual Read/Write(Stream s) и public virtual IEditor GetEditor(). Тогда и комбинируй как хошь и изменения удобно делать. Но всё вместе, что с одной стороны хорошо, а с другой плохо.Вот как бы всё разделить, но чтобы осталось удобно изменения делать?
из всего этого описания понять можно очень мало. потому и посоветовать можно только одно: придумать удобную абстракцию. и будет вам удобно.
если хотите конкретнее и полезнее обсуждение сделать, упростите задачу до примитива, но приведите простой КОНКРЕТНЫЙ пример, чтобы можно было не абстрактно говорить об абстракциях, а на конкретном примере (не нужно никакого кода, или почти никакого!) - о конкретных абстракциях. иначе даже вам будет сложно оценить, какая абстракция есть удобная, а какая - нет.
"итак, представим себе что имеем записи о клиентах/данные о расходах/породы собак/... , которые требуется хранить (или уже определено нами/ненами, где и как они хранятся, тогда рассказать), доставать, отображать, визуально редактировать и сохранять вместе с историей для возможного отката/анализа. ..." или где-то так.
и тут же - примерчик этих данных в формате "хэллоу уорлд!", с хэллоууордным же примером/-ами юзкэйсов.
часть объекта данных, т.е. объект данных сам себя считывает из потока или записывает в поток.
-----
Да, чистое ООП - все понятно.
Вот только уже не является самым удобным вариантом.
решает наиболее часто встречающиеся проблемы максимально абстрагировавшись от предметной области
-----
Ну наконец-то. И каков следующий уровень абстрагирования?
Суда про всему, ты не знаешь чего ты хочешь.
-----
Тут ты сильно не прав.
Я - ленив до безобразия - потому не хочется писать "лишний" код...
А ИО & Е - хочется и хочется автоматом и нужного видa...
Фактически IEditor повторяет структуру объекта и это не редактор, а IDataObjectXDefinition
public interface IEditor { string Name { get; } int Length { get; } IEnumerable<IEditor> SubItems { get; } bool IsAvailable { get; set; } }
Сейчас именно так и сделано. Из "читалки" выходят интерфейсы данных, имплементация внутри. Думал может, что лучше можно найти.
Объекты то ведь не такие простые, их еще нужно удалять и модифицировать и внутри еще списки, то бишь нужна ObservableCollection и WindowsBase assembly. Что не очень то хочется для Консольных и Винформс проектов.
До "писалки" пока еще не дошел, будут наверняка новые проблемы.
Или ты в лучших традициях Murr'а утаил какие-то детали?
Вполне возможно Не так и просто все коротко описать. Я вот когда первый вариант писал, нашел одно решение, но после оказалось мало.
Ну и понятно что 100% решения не будет, но иногда высказывания могут дать новый импульс для размышлений.
но приведите простой КОНКРЕТНЫЙ пример
Хм, простой... Не знаю пока.
Но вообще с делением на "конкретников" и "абстрактников" познакомился давно. Как то объяснял коллеге что то и потом смотрю, что не понимает он решение. В итоге выяснилось что мы на разных полюсах. Без конкретного примера ему ничего нельзя было рассказывать.
Но зато как это понял сразу пошло нормально. Так что сорри, привык максимально абстрактно описывать.
Если немного конкретно.. и попроще..
Есть объект "параметр", читает имя поля и тип объекта, если тип объекта numeric, то читается еще значение по умолчанию. Затем читается конкретный тип.
Из типов: bool, int, double, string, различные комбинации Dictionary (int-string, string-double, int-double) включая еще и различные вложенные словари x-Dictionary<k,y>
И это всё нужно показать в одной таблице и также иметь возможность редактирования всех типов данных. При этом нужно еще пользовать С++ либу для чтения.
Кроме этого есть еще и другие подобные объекты.
и снова вы "паки-паки", "иже херувимы". языками не владеете?
вы ведь уже и "кодировать начали". не решили только пока, что именно. я действительно, не поняв, чего хотят, не въезжаю. ладно, примем, что это я туплю, не берите в голову. приятных вам абстракций : )
паки-паки...
уже и "кодировать начали"
Нет времени на раздумья и поиск лучшего решения. Это всё как бы на будущее ну и ли в процессе что то изменить в лучшую сторону.
Заказчика интересует конкретный продукт в минимальные сроки.. Всё остальное интересует только меня.
я действительно, не поняв, чего хотят, не въезжаю
Ну значит что то не так описал Просто не знаю как описать лучше. Я и сам то пару недель врубался что нужно, а как это за пару минут описать...
относится к заглавию и первому посту
что такое:
0. объект данных
1. отдельный проект
2. внутренний проект
3. наружа
4. запись/чтение (и куда/откуда)
5. в " изменения удобно делать" какие изменения
6. что "все вместе" и с какой стороны что
7. разделение от чтения/записи и отображения
Заказчика интересует конкретный продукт в минимальные сроки..
ну, это было вашей задачей (и сейчас еще остается), разъяснить клиенту, в какие реальные сроки какого качества и цены сопровождения продукт он может реально поличить. чтобы родился жизнеспособный полноценный ребенок, необходимо 9 месяцев. до семи, говорят, тоже потом догонит. но кто хочет за 5-6 родить, получит слабого и отсталого, если вообще живого. и это не зависит никак от того, что интересует или не интересует заказчика.
Фактически IEditor повторяет структуру объекта и это не редактор, а IDataObjectXDefinition
Тут не совсем понятно, что тогда такое IEditor. Я думал, что это ViewModel для редактора.
Если уж ты говоришь о ObservableCollection, значит речь о WPF и, следовательно, в MVVM.
Итак, модель у тебя каким-то образом создает (считывает из файла, получает из БД, генерирует случайным образом) объекты с данными. Кроме этого, у нас есть View - редактор и и есть ViewModel - этот объект должен знать структуру объекта с данными и должен знать, что будет отображать редактор.
Т.е. никаких сюрпризов тут нет и быть не может. View точно знает какие данные он может отобразить (т.е. работает с заранее известным интерфейсом ViewModel). ViewModel в свою очередь точно знает модель и интерфейсы всех отображаемых данных.
Так в чем проблема-то? :)
Тут не совсем понятно, что тогда такое IEditor. Я думал, что это
а мне также совсем непонятно, как вам хоть что-то понятно. вы привыкли выполнять задачи на основании догадочной документации? мне когда-то (один раз за все время) пришлось начинать с "техзадания", похожего на первый пост Алекса. месяца два мурыжил его, пока не получился некий документ (документом он в строгом смысле не был), позволяющий сделать вывод о том, что должно быть разработано, что оно должно делать (а чего - нет) и как. а до того только слышал от шефа "сроки поджимают! когда ты наконец приступишь к кодированию!". неприятное время было, но иначе просто не могу. сорри.
а мне также совсем непонятно, как вам хоть что-то понятно. вы привыкли выполнять задачи на основании догадочной документации?
оно почти всегда так. есть какие-то обрывки информации и приходится поятоянно что-то уточнять, переделывать итд.
В худшем случае у меня происходит так: шеф 2-3-4 месяца переписывается с клиентом, потом приходит с километровой простыней е-мылов и спрашивает "сколько на это надо времени", потом опять пауза на пару месяцев, потом приходит за неделю до дедлайна и говорит, что надо оставить все задачи и пилить новую фичу. Постит при этом ту самую километровую простыню е-мылов типа там есть вся информация :D
значит, нужно самому взяться и написать какое-нибудь примитивное техзадание и дать всем на подпись или просто на ознакомление. на это уйдет время, но сэкономится больше. ясно, писать доки никто не любит, но без этого просто нельзя. ну, если задача - не хэллоуорлд какой-нибудь : )
Проблема в том, что когда я получаю задание, то дедлайн уже "вчера".
Ну и подписывать мне не с кем, я с клиентами на прямую не общаюсь. Так что обсуждать могу только с шефом. А давать что-то на подпись шефу - это уже перебор :) Если мне что-то не понятно, то задаю вопрос в емыле и все.
жаль, что алекс исчез, и мне его так и не удалось раскачать на вразумительное условие задачи. ведь иногда стоит задачу переформулировать, и рашение уже читается из условия.
гешефтсидея: вынудить ИИ из потока имэйлов шефа выстроить несколькостраничное техзадание. вот только как их удобнее разделить от чтения/записи и отображения ; )
имею отрицательный опыт в этом плане. руководитель проекта как-то получил свежее техзадание на очередной проект (крупная фича), и говорит, что я, мол, доку на сервер выложил, но чтоб тебе не читать и не морочить голову, я тебе сейчас за 5 минут все обрисую. и обрисовал. выглядело вполне плаузибельно. я и сваял на первый тест нечто, что он описал. оказалось, что одну "мелкую деталь" он то ли опустил, то ли неправильно изложил, как я узнал, прочтя таки все техзадание от корки до корки, но пришлось переделывать, ставить заплатки и пр. с тех пор ВСЕГДА хочу начать с того, что ознакомлюсь с документом. в дальнейшем этот же руководитель проекта вел себя точно также, я его вежливо дослушивал до конца, благодарил, но, выйдя от него, шел читать техзадание. и НИ РАЗУ не пожалел. если бы было нечего читать, я бы начал с того, что сам бы хотя бы пару страниц написал. хотя бы в виде перечня каких-то утверждений. что должно быть, и чего не должно. и держал бы актуальным. а документация в виде шефа - это ненадежно. дай ему бог здоровья, но сегодня это особенно актуально.