Опт. решение для разделения объектов данных от чтения/записи и отображения
Итак есть объект данных. Этот объект читается в отдельном проекте и выдается наружу для показа и редактирования. Выданный объект не должен иметь никаких видимых методов для записи и чтения.
Внутренний проект для чтения/записи должен конечно иметь функции чтения и записи объекта. Объектов довольно много так что расход памяти и скорость играют роль.
Чисто с отдельными простыми объектами решений может быть много, а вот когда объекты наследуются, да и еще динамически создаются с различными типами данных, когда нет даже возможности общий класс сделать, то удобного решения пока не вижу.
Наиболее удобно иметь в классе данных 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 интерфейса:
-----
Насколько Я понял - он как раз хочет "имплементацию" не в составе класса, а вообще в другой либе.
И... это... интерфейс у тебя проблемный - либо работаем с потоками, либо с именами файлов. Смешанное - оно тяжко... тяжелее только недописанное...
Ну так и сделаешь 2 интерфейса:
И как мне эти интерфейсы воткнуть в редактор? Которому надо что то типа "ColumnAbc = item.Length". Вытаскивать всё самому из объекта довольно долго. Да и структура объекта довольно сложная
хочет "имплементацию" не в составе класса, а вообще в другой либе.
И это тоже. При чтении нужно пользоваться старой плюсовой либой а там столько "лишних" ссылок.
Ну и данные нужны сейчас для 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
- запрошена не имплементация ИЕдитор в классе, а наличие метода ГетЕдитор, который возвращает лежащий непонятно где редактор, умеющий работать с объектом, но не знающий фактический тип объекта...
Или ты в лучших традициях Murr'а утаил какие-то детали?
-----
Нее, скорее Программист прочитал в меру своего понимания задачи...
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...