Deutsch

Опт. решение для разделения объектов данных от чтения/записи и отображения

535  1 2 все
AlexNek патриот10.03.20 19:10
AlexNek
10.03.20 19:10 

Итак есть объект данных. Этот объект читается в отдельном проекте и выдается наружу для показа и редактирования. Выданный объект не должен иметь никаких видимых методов для записи и чтения.

Внутренний проект для чтения/записи должен конечно иметь функции чтения и записи объекта. Объектов довольно много так что расход памяти и скорость играют роль.

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

Наиболее удобно иметь в классе данных public virtual Read/Write(Stream s) и public virtual IEditor GetEditor(). Тогда и комбинируй как хошь и изменения удобно делать. Но всё вместе, что с одной стороны хорошо, а с другой плохо.

Вот как бы всё разделить, но чтобы осталось удобно изменения делать?

#1 
Murr патриот10.03.20 20:05
Murr
NEW 10.03.20 20:05 
в ответ AlexNek 10.03.20 19:10

Выданный объект не должен иметь никаких видимых методов для записи и чтения.

Вот как бы всё разделить, но чтобы осталось удобно изменения делать?

-----

Пример тебе дан в виде ISerializable & [Serializable]

Но из постановки задачи Я пока не вижу когда тебе надо связать Реад/Врите() с фактическими объектами.

Мне, например, уже не хочется иметь внутренние Реад/Врите - они хорошо, но уже никак не достаточно.

Хочется иметь один более/менее стандартизованный вызов, но совершенно дифференцированный результат.

Пример - есть производный от ДатаРов объект - хочется иметь ИнсертСтреам, ДелетеСтреам, ХмлОУТ/ИН, БинОут/ИН и т.п.



когда нет даже возможности общий класс сделать

-----

В .Нет всегда есть общий класс. Там где его нету - можно ввести принудительно...




#2 
AlexNek патриот10.03.20 20:45
AlexNek
NEW 10.03.20 20:45 
в ответ Murr 10.03.20 20:05
Я пока не вижу когда тебе надо связать Реад/Врите() с фактическими объектами

А разве это имеет какое то значение?

В конкретном случае, данные находятся в двоичном формате в файле на диске.

Нужно прочитать и отобразить данный файл. Внутри списки различных объектов. От bool,int ,string до Dictionary и более сложных объектов.


В .Нет всегда есть общий класс.

А какой мне смысл от объекта? Ведь каждый объект данных имеет еще дополнительные поля.

#3 
Murr патриот10.03.20 22:25
Murr
NEW 10.03.20 22:25 
в ответ AlexNek 10.03.20 20:45

А какой мне смысл от объекта?

-----

??? - Ну либо ты имеешь возможность написать Реад(объект)/Врите(объект) и внутрь запихать какой-то общий диспетчер, либо надо писать под каждую бранчь отдельно...

Наличие и количество производных типов роли не играет. Ролю играет количество различных базовых типов. В .Нет он один - достаточно написать одну пару методоv.


А разве это имеет какое то значение?

-----

Для меня - уже имеет - мне надо заменить результат трансляции Т4 шаблона.

Билли слепил нечто, в чем вывод размазан по коду и нет вариантов его заменить.

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


#4 
AlexNek патриот10.03.20 22:54
AlexNek
NEW 10.03.20 22:54 
в ответ Murr 10.03.20 22:25
Ну либо ты имеешь возможность написать Реад(объект)/Врите(объект)

Даже такой возможности не вижу смущ

Нужно то преобразовать вначале в конкретный тип. А как быть с иерархией классов?

Ну например, сейчас я выдаю наверх только интерфейсы, все классы внутри реад/Врите. А вот куда девать редакторы вьюверы? Они то должны быть привязаны к конкретной имплементации.

#5 
Murr патриот10.03.20 23:36
Murr
NEW 10.03.20 23:36 
в ответ AlexNek 10.03.20 22:54

Даже такой возможности не вижу

-----

А что мешает? Тип - есть, написать метод с параметром типа - можно...


Они то должны быть привязаны к конкретной имплементации.

-----

Фабрика или фабричный метод?

В основном вопрос будет - когда именно компиляется имплементация - в общем построении проекта или позднее, в ран-тайме...

Если первое - нужно определение типa.

Если второе - нужна атрибутика...

#6 
Программист коренной житель11.03.20 11:43
NEW 11.03.20 11:43 
в ответ AlexNek 10.03.20 19:10

Я не совсем понял твою проблему...


Наиболее удобно иметь в классе данных 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 :)

#7 
Murr патриот11.03.20 12:54
Murr
NEW 11.03.20 12:54 
в ответ Программист 11.03.20 11:43

Ну так и сделаешь 2 интерфейса:

-----

Насколько Я понял - он как раз хочет "имплементацию" не в составе класса, а вообще в другой либе.


И... это... интерфейс у тебя проблемный - либо работаем с потоками, либо с именами файлов. Смешанное - оно тяжко... тяжелее только недописанное...

#8 
AlexNek патриот11.03.20 21:38
AlexNek
NEW 11.03.20 21:38 
в ответ Программист 11.03.20 11:43
Ну так и сделаешь 2 интерфейса:

И как мне эти интерфейсы воткнуть в редактор? Которому надо что то типа "ColumnAbc = item.Length". Вытаскивать всё самому из объекта довольно долго. Да и структура объекта довольно сложная

#9 
AlexNek патриот11.03.20 22:02
AlexNek
NEW 11.03.20 22:02 
в ответ Murr 11.03.20 12:54
хочет "имплементацию" не в составе класса, а вообще в другой либе.

И это тоже. При чтении нужно пользоваться старой плюсовой либой а там столько "лишних" ссылок. шок

Ну и данные нужны сейчас для WPF, завтра Winforms или Console.


Вот интересный пример:

Из Winforms есть запросы к 32 битной С++ Манажед+анманагед либе чтения данных - всё работает, все тоже самое повторяем для WPF, работает пока данные не цепляются к биндингу на форму. Как цепляются - сразу вылетает "повреждение памяти" в плюсах.

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


#10 
Murr патриот12.03.20 01:15
Murr
NEW 12.03.20 01:15 
в ответ AlexNek 11.03.20 21:38

Вытаскивать всё самому из объекта довольно долго. Да и структура объекта довольно сложная

-----

А как ты вообще хотел?

Либо ты работаешь с объектом, либо строишь какие-то метаданные на базе объекта и работаешь с ними.

Во втором случае у тебя все сложнее, объемнее, но более управляемо при сторонних редакторах...

#11 
Программист коренной житель12.03.20 08:53
NEW 12.03.20 08:53 
в ответ AlexNek 11.03.20 21:38
И как мне эти интерфейсы воткнуть в редактор? Которому надо что то типа "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

#12 
Murr патриот12.03.20 11:28
Murr
NEW 12.03.20 11:28 
в ответ Программист 12.03.20 08:53

Так в чем проблема-то?

-----

Насколько Я понимаю - минимум две проблемы:

- void IReadWrite.Read(Stream s) & void IReadWrite.Write(Stream s) должны быть имплементированы там, где никто не знает об class SomeObject безум

- запрошена не имплементация ИЕдитор в классе, а наличие метода ГетЕдитор, который возвращает лежащий непонятно где редактор, умеющий работать с объектом, но не знающий фактический тип объекта... смущ

#13 
Murr патриот12.03.20 11:31
Murr
NEW 12.03.20 11:31 
в ответ Программист 12.03.20 08:53

Или ты в лучших традициях Murr'а утаил какие-то детали?

-----

Нее, скорее Программист прочитал в меру своего понимания задачи...

#14 
Программист коренной житель12.03.20 12:43
NEW 12.03.20 12:43 
в ответ Murr 12.03.20 11:28
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

#15 
Murr патриот12.03.20 14:09
Murr
NEW 12.03.20 14:09 
в ответ Программист 12.03.20 12:43

должен имплементировать этот интерфейс

-----

Там, наверху, написано пожелание удобства. В данном варианте - неудобно.

Дальше будет либо медленно - рефлектионом через объект, либо относительно быстро - по метаданным.


стрелять себе в ногу и потом придумывать решения для элементарных задач

-----

Ээээ...

помнится, был файловый ввод/вывод... вполне себе элементарное решение...

потом файловый ИО заменили потоковым... вполне себе элементарное решение...

вроде как потоковый заменили сериализатором... таки тоже вполне элементарное решение...

И чаво это народ себе в ноги постоянно стреляет? смущ


И - да - таки тоже хочу иметь удобное и красивое решение... простая сериализация уже не устраивает...

#16 
Программист коренной житель12.03.20 14:38
NEW 12.03.20 14:38 
в ответ Murr 12.03.20 14:09
Там, наверху, написано пожелание удобства. В данном варианте - неудобно.

там, наверху, написано следующее:

Наиболее удобно иметь в классе данных public virtual Read/Write(Stream s)

т.е. Read и Write - часть объекта данных, т.е. объект данных сам себя считывает из потока или записывает в поток.

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


помнится, был файловый ввод/вывод... вполне себе элементарное решение...

да, но узкой специализации


потом файловый ИО заменили потоковым... вполне себе элементарное решение...

только не заменили, а объеденили считывание любых данных одной абстракцией.


вроде как потоковый заменили сериализатором... таки тоже вполне элементарное решение...

сериализатор решает также узкую задачу.


И чаво это народ себе в ноги постоянно стреляет?

Не стреляет. Народ решает наиболее часто встречающиеся проблемы максимально абстрагировавшись от предметной области.


И - да - таки тоже хочу иметь удобное и красивое решение... простая сериализация уже не устраивает...

Суда про всему, ты не знаешь чего ты хочешь. И не знаешь, чем не устраивает тебя сериализация :D

#17 
moose коренной житель12.03.20 16:17
moose
NEW 12.03.20 16:17 
в ответ Murr 12.03.20 14:09
И - да - таки тоже хочу иметь удобное и красивое решение... простая сериализация уже не устраивает...

тогда только стерилизация : )

ばかが過半数である場合、それは彼らが正しいという意味ではありません
#18 
moose коренной житель12.03.20 16:27
moose
NEW 12.03.20 16:27 
в ответ AlexNek 10.03.20 19:10, Последний раз изменено 12.03.20 16:29 (moose)
Итак есть объект данных. Этот объект читается в отдельном проекте и выдается наружу для показа и редактирования. Выданный объект не должен иметь никаких видимых методов для записи и чтения. Внутренний проект для чтения/записи должен конечно иметь функции чтения и записи объекта. Объектов довольно много так что расход памяти и скорость играют роль. Чисто с отдельными простыми объектами решений может быть много, а вот когда объекты наследуются, да и еще динамически создаются с различными типами данных, когда нет даже возможности общий класс сделать, то удобного решения пока не вижу. Наиболее удобно иметь в классе данных public virtual Read/Write(Stream s) и public virtual IEditor GetEditor(). Тогда и комбинируй как хошь и изменения удобно делать. Но всё вместе, что с одной стороны хорошо, а с другой плохо.Вот как бы всё разделить, но чтобы осталось удобно изменения делать?

из всего этого описания понять можно очень мало. потому и посоветовать можно только одно: придумать удобную абстракцию. и будет вам удобно.


если хотите конкретнее и полезнее обсуждение сделать, упростите задачу до примитива, но приведите простой КОНКРЕТНЫЙ пример, чтобы можно было не абстрактно говорить об абстракциях, а на конкретном примере (не нужно никакого кода, или почти никакого!) - о конкретных абстракциях. иначе даже вам будет сложно оценить, какая абстракция есть удобная, а какая - нет.


"итак, представим себе что имеем записи о клиентах/данные о расходах/породы собак/... , которые требуется хранить (или уже определено нами/ненами, где и как они хранятся, тогда рассказать), доставать, отображать, визуально редактировать и сохранять вместе с историей для возможного отката/анализа. ..." или где-то так.


и тут же - примерчик этих данных в формате "хэллоу уорлд!", с хэллоууордным же примером/-ами юзкэйсов.

ばかが過半数である場合、それは彼らが正しいという意味ではありません
#19 
Murr патриот12.03.20 18:42
Murr
NEW 12.03.20 18:42 
в ответ Программист 12.03.20 14:38

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

-----

Да, чистое ООП - все понятно.

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


решает наиболее часто встречающиеся проблемы максимально абстрагировавшись от предметной области

-----

Ну наконец-то. И каков следующий уровень абстрагирования?



Суда про всему, ты не знаешь чего ты хочешь.

-----

Тут ты сильно не прав.

Я - ленив до безобразия - потому не хочется писать "лишний" код...

А ИО & Е - хочется и хочется автоматом и нужного видa...

#20 
1 2 все