:: Visual Foxpro, Foxpro for DOS
Сохранить переменную типа Object в файл
Chips
Автор

Сообщений: 93
Дата регистрации: 11.02.2016
Добрый день.

Как сохранить переменную типа Object в файл?

Может есть какая нибудь простая команда, вроде SAVE TO / RESTORE FROM ?
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Для какой цели? И что именно должно сохраняться?
При копировании/сериализации объектов есть как минимум 2 разные стратегии - Deep Copy и Shallow Copy - в зависимоти от того как поступать с полями объекта содержащими ссылки на другие объекты - копировать/сериализовать их, или только копировать/сериализовать поля примитивных типов данных.
Встроенных механизмов что копирования (клонирования), что сериализации/десериализации в фоксе нет. Свои сделать можно, но лично я в этом не вижу никакого смысла.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
Chips
Автор

Сообщений: 93
Дата регистрации: 11.02.2016
Igor Korolyov
Для какой цели? И что именно должно сохраняться?

define class Settings as Custom
PathToShablon = "C:\test\Shablon\"
PathToXlsFiles = "C:\test\In\"
PathToOut = "C:\test\out\"
ENDDEFINE

Хочу сделать класс для настроек.



Исправлено 1 раз(а). Последнее : Chips, 03.08.17 14:09
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Обычно в фоксе делают наоборот - класс ЧИТАЮЩИЙ некоторый настроечный файл (ini/xml/dbf/txt) и возвращающий эти самые настройки по запросу. Он может возвращать значения через метод - типа GetSetting("Name"), а может и динамически добавлять свойства .AddProperty() в соответствии с тем что было считано из файла.
Не сложно в этом же классе сделать и обратное сохранение значений настроек в файл.
В простейшем случае вообще ограничиваются парой обычных "старорежимных функций" для чтения и для записи настройки по имени (но класс всё же лучше).

В шарпе, к слову, тоже никто не "сохраняет объект в файл" для чтения/записи настроек приложения - там есть свой, достаточно сложный и развитый механизм для хранения настроек. И VisualStudio просто генерирует класс Settings для использования этого механизма.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
Chips
Автор

Сообщений: 93
Дата регистрации: 11.02.2016
Igor Korolyov
но класс всё же лучше

хм... Значит надо добавить к классу методы "Сохранить" и "Восстановить" настройки?

define class Settings as Custom
PathToShablon = "C:\test\Shablon\"
PathToXlsFiles = "C:\test\In\"
PathToOut = "C:\test\out\"
PROCEDURE SaveSettings
ENDPROC
PROCEDURE LoadSettings
ENDPROC
ENDDEFINE
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
К примеру как-то так (очень грубо и упрощённо - для варианта хранения настроек в тривиальном dbf)
define class Settings as Custom
AutoRead = .T.
PROCEDURE Init
IF This.AutoRead
This.LoadSettings()
ENDIF
ENDPROC
PROCEDURE LoadSettings
SELECT 0
USE Settings
LOCAL lcName, luValue
SCAN ALL
lcName = This.CheckName(Settings.Name)
luValue = This.DeserializeValue(Settings.Value, Settings.Type)
This.AddProperty(m.lcName, m.luValue)
ENDSCAN
USE IN SELECT("Settings")
ENDPROC
PROCEDURE SaveSettings
SELECT 0
USE Settings
LOCAL lcName, lcValueAsString
SCAN ALL
lcName = This.CheckName(Settings.Name)
IF PEMSTATUS(This, m.lcName, 5)
luValue = GETPEM(This, m.lcName)
lcValueAsString = This.SerializeValue(m.luValue)
REPLACE Name WITH m.lcValueAsString, Type WITH VARTYPE(m.luValue)
ENDIF
ENDSCAN
USE IN SELECT("Settings")
ENDPROC
...
enddefine

Методы для контроля/преобразования "абы какого" названия настройки к корректному и непротиворечивому для фокса "имени свойства" (например не пересекающегося со "встроенными" именами методов/свойств, не начинающегося с цифры, не содержашего пробелов и т.п.), для непротиворечивого преобразования значения произвольного типа к строке и обратно (например для дат - чтобы способ преобразования не зависел от настроек SET DATE, SET CENTURY и т.п. для чисел - от SET POINT и т.д.) - это всё уж сам придумай как сделать
Заодно обработку ошибок прикрутить (для корректного отслеживания ситуаций типа нет файла настроек, или если вместо "числа" в настройке с типом N одни буквы сидят)...


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
Chips
Автор

Сообщений: 93
Дата регистрации: 11.02.2016
Не так уж и просто, как может показаться.

Igor Korolyov
Заодно обработку ошибок прикрутить

Ок. Будем работать...

Спасибо за пример.
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Хм, а в чём сложности то? Простейшая логика - взяли хранилище, перебираем что там есть, добавляем свойства (если свойство уже есть, просто значение новое в него помещаем - благо AddProperty так работает). Всё прочее - чисто служебная обвязка. Ну да, для удобства ещё можно группу методов типа Add(name, value), AddIfNotExist(name, value), Remove(name) - чтобы убрать надобность в "ручной" работе с хранилищем настроек (начальное наполнение, удаление устаревших и т.п.)


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
lemenev

Сообщений: 112
Дата регистрации: 23.06.2022
Проглядывая старые темы, я наткнулся на идею, предложенную Игорем Королёвым. Она меня заинтересовала, и мне захотелось её реализовать. То, что получилось выкладываю на всеобщее обозрение. Программа представляет для меня не практический, а учебный интерес, так что любая конструктивная критика по методологии, реализации, оформлению только приветствуется. Для того и публикую.
* Класс настроек
* Идея принадлежит Игорю Королёву
* forum.foxclub.ru
* Класс для работы с настройками программы
* Методы:
* LoadSettings - Загрузка всех настроек из файла
* SaveSettings - Сохранение всех настроек из памяти в файл
* Add(Name, Value) - Добавлениие одной настройки в файл
* Remove(Name) - Удаление одной настройки из файла
* ShowFile - Показ всех настроек из файла
* ShowMemory - Показ всех настроек из памяти
DEFINE CLASS Settings AS Custom
PROTECTED Old_CENTURY, Old_CURRENCY, Old_CURRENCY1, Old_DATE, Old_EXACT, ;
Old_FIXED, Old_HOURS, Old_MARK, Old_POINT, Old_SEPARATOR
PROTECTED Old_Dbf_Area, Alias, ErrSign
Old_CENTURY =SET('CENTURY')
Old_CURRENCY =SET('CURRENCY') && LEFT
Old_CURRENCY1=SET('CURRENCY',1) && $
Old_DATE =SET('DATE')
Old_EXACT =SET('EXACT')
Old_FIXED =SET('FIXED')
Old_HOURS =SET('HOURS')
Old_MARK =SET('MARK')
Old_POINT =SET('POINT')
Old_SEPARATOR=SET('SEPARATOR')
* Функция SELECT( ) возвращает номер текущей рабочей области, если действует установка SET COMPATIBLE = OFF
Old_Dbf_Area = SELECT()
Alias = 'Settings' && имя файла с настройками
ErrSign = 'XXXXX' && признак ошибки
PROCEDURE Init
* Открытие/создание файла настроек
IF USED(This.Alias) && файл уже используется
SELECT (This.Alias)
ELSE
IF FILE(This.Alias+'.dbf') && файл существует
USE (This.Alias) IN 0 ORDER Name EXCLUSIVE
ELSE && создаём файл
CREATE TABLE (This.Alias) FREE CODEPAGE = 1251 ;
(Name C(20), Type C(1), Value C(50))
INDEX ON Name TAG Name COLLATE 'RUSSIAN'
ENDIF
ENDIF
* Настроим среду FoxPro
SET CENTURY ON
SET CURRENCY LEFT
SET CURRENCY TO '§'
SET DATE GERMAN
SET EXACT ON
SET FIXED OFF
SET HOURS TO 24
SET MARK TO '.'
SET POINT TO '.'
SET SEPARATOR TO ','
ENDPROC
PROCEDURE Destroy
* Закрытие файла настроек
USE IN SELECT(This.Alias)
SELECT(This.Old_Dbf_Area)
* Вернём настройки среды FoxPro
LOCAL xCENTURY, xCURRENCY, xEXACT, xFIXED
xCENTURY = This.Old_CENTURY
SET CENTURY &xCENTURY
xCURRENCY = This.Old_CURRENCY
SET CURRENCY &xCURRENCY
SET CURRENCY TO (This.Old_CURRENCY1)
SET DATE (This.Old_DATE)
xEXACT = This.Old_EXACT
SET EXACT &xEXACT
xFIXED = This.Old_FIXED
SET FIXED &xFIXED
SET HOURS TO (This.Old_HOURS)
SET MARK TO (This.Old_MARK)
SET POINT TO (This.Old_POINT)
SET SEPARATOR TO (This.Old_SEPARATOR)
ENDPROC
PROCEDURE LoadSettings
* Загрузка всех настроек из файла
LOCAL lcName, luValue
SCAN ALL
lcName = This.CheckName(Settings.Name)
luValue = This.DeserializeValue(Settings.Value, Settings.Type)
IF (lcName = This.ErrSign) OR (VARTYPE(m.luValue) = 'C' AND m.luValue = This.ErrSign)
* ничего не делаем
ELSE
This.AddProperty(m.lcName, m.luValue)
ENDIF
ENDSCAN
ENDPROC
PROCEDURE SaveSettings
* Сохранение всех настроек из памяти в файл
LOCAL lcName, luValue, lcValueAsString
LOCAL lnCount, ar(1), i, ErrTitel
ErrTitel = 'CLASS Settings.SaveSettings'
* Получим список имён всех настроек в памяти
* 'B' - свойства созданные с использованием метода AddProperty
lnCount = AMEMBERS(ar,This,0,'B')
IF m.lnCount > 0
FOR i = 1 TO m.lnCount
lcName = ar(i) && имя заведомо допустимо
luValue = GETPEM(This, m.lcName)
* Проверка допустимости значения
lcValueAsString = This.SerializeValue(m.luValue)
IF lcValueAsString = This.ErrSign
* недопустимое значение свойства
LOOP
ENDIF
* Сохраним в файл
IF SEEK(m.lcName)
REPLACE Type WITH VARTYPE(m.luValue), Value WITH m.lcValueAsString
ELSE
INSERT INTO (This.Alias) (Name, Type, Value) VALUES ;
(m.lcName, VARTYPE(m.luValue), m.lcValueAsString)
ENDIF
ENDFOR
ELSE
MESSAGEBOX('В памяти ещё нет ни одной настройки',0,m.ErrTitel)
ENDIF
ENDPROC
PROCEDURE Add
* Добавлениие одной настройки в файл
LPARAMETERS luName, luValue
LOCAL lcValueAsString
* Проверка допустимости имени
lcName = This.CheckName(m.luName)
IF lcName = This.ErrSign
* недопустимое имя свойства
RETURN
ENDIF
* Проверка допустимости значения
lcValueAsString = This.SerializeValue(m.luValue)
IF lcValueAsString = This.ErrSign
* недопустимое значение свойства
RETURN
ENDIF
* Сохраним в файл
IF SEEK(m.lcName)
REPLACE Type WITH VARTYPE(m.luValue), Value WITH m.lcValueAsString
ELSE
INSERT INTO (This.Alias) (Name, Type, Value) VALUES ;
(m.lcName, VARTYPE(m.luValue), m.lcValueAsString)
ENDIF
ENDPROC
PROTECTED PROCEDURE CheckName
* Проверка имени свойства на допустимость
LPARAMETERS luName
LOCAL lcName, ErrTitel, ar(1,1), lnCount
lcName = This.ErrSign
ErrTitel = 'CLASS Settings.CheckName'
* Составим список запрещённых имён
* 1 - Определяет, что массив содержит имена системных и защищённых свойств,
* а также имена процедур класса
* P - Свойства, методы, события с характеристикой "Protected"
* N - Внутренние, базовые свойства, методы, события класса
lnCount = AMEMBERS(ar,This,1,'PN')
DO CASE
CASE VARTYPE(luName) <> 'C'
MESSAGEBOX('Тип для задания имени свойства не символьный'+CHR(13)+VARTYPE(m.luName),0,m.ErrTitel)
CASE ISDIGIT(LTRIM(luName))
MESSAGEBOX('Имя свойства начинается с цифры'+CHR(13)+m.luName,0,m.ErrTitel)
CASE SPACE(1) $ ALLTRIM(luName)
MESSAGEBOX('В имени свойства есть пробел'+CHR(13)+m.luName,0,m.ErrTitel)
CASE ASCAN(ar, m.luName, 1, m.lnCount, 1) > 0
MESSAGEBOX('Недопустимое имя свойства'+CHR(13)+'Данное имя зарезервировано'+CHR(13)+m.luName,0,m.ErrTitel)
OTHERWISE
lcName = ALLTRIM(m.luName)
ENDCASE
RETURN m.lcName
ENDPROC
PROTECTED PROCEDURE SerializeValue
* Преобразуем текущее значение настройки в символьный вид
LPARAMETERS luValue
LOCAL lcValue, ErrTitel
ErrTitel = 'CLASS Settings.SerializeValue'
IF AT(VARTYPE(m.luValue), 'GOQUX') > 0
MESSAGEBOX('Недопустимый тип значения свойства'+CHR(13)+VARTYPE(m.luValue),0,m.ErrTitel)
RETURN This.ErrSign
ENDIF
IF VARTYPE(m.luValue) = 'C'
lcValue = m.luValue
ELSE
lcValue = TRANSFORM(m.luValue)
ENDIF
RETURN m.lcValue
ENDPROC
PROTECTED PROCEDURE DeserializeValue
* восстановим состояние настройки из файла
LPARAMETERS lcValue, lcType
LOCAL luValue, ErrTitel, lError
ErrTitel = 'CLASS Settings.DeserializeValue'
LOCAL nYear, nMonth, nDay, nHours, nMinutes, nSeconds
IF VARTYPE(m.lcValue) <> 'C'
MESSAGEBOX('Свойство для преобразования не символьного типа'+CHR(13)+VARTYPE(m.lcValue),0,m.ErrTitel)
ENDIF
IF VARTYPE(m.lcType) <> 'C'
MESSAGEBOX('Указанный тип преобразования не символьного типа'+CHR(13)+VARTYPE(m.lcType),0,m.ErrTitel)
ENDIF
lcValue = TRIM(m.lcValue)
TRY
DO CASE
CASE m.lcType = 'C'
luValue = m.lcValue
CASE m.lcType = 'D'
luValue = CTOD(m.lcValue)
CASE m.lcType = 'L'
luValue = EVALUATE(m.lcValue)
CASE m.lcType = 'N'
luValue = VAL(m.lcValue)
CASE m.lcType = 'T'
nYear = VAL(SUBSTR( m.lcValue, 7, 4 ))
nMonth = VAL(SUBSTR( m.lcValue, 4, 2 ))
nDay = VAL(SUBSTR( m.lcValue, 1, 2 ))
nHours = VAL(SUBSTR( m.lcValue,12, 2 ))
nMinutes = VAL(SUBSTR( m.lcValue,15, 2 ))
nSeconds = VAL(SUBSTR( m.lcValue,18, 2 ))
luValue = DATETIME(nYear, nMonth, nDay, nHours, nMinutes, nSeconds)
CASE m.lcType = 'Y'
* Нужно убрать разделители разрядов
luValue = CAST(STRTRAN(m.lcValue,',','') AS Currency)
ENDCASE
CATCH TO lError
MESSAGEBOX('Ошибка в данных значения свойства'+CHR(13)+m.lcValue,0,m.ErrTitel)
luValue = This.ErrSign
ENDTRY
IF VARTYPE(m.luValue) <> Type
MESSAGEBOX('Несоответствие указанного типа и типа данных значения'+;
' свойства'+CHR(13)+Type+' и '+m.lcValue,0,m.ErrTitel)
luValue = This.ErrSign
ENDIF
RETURN m.luValue
ENDPROC
PROCEDURE Remove
* Удаление одной настройки из файла
LPARAMETERS luName
LOCAL lcName
lcName = This.CheckName(m.luName)
IF SEEK(m.lcName)
DELETE
PACK
ENDIF
ENDPROC
PROCEDURE ShowFile
* Показ всех настроек из файла
LOCAL ErrTitel
ErrTitel = 'CLASS Settings.ShowFile'
IF RECCOUNT() > 0
BROWSE TITLE 'Настройки из файла '+This.Alias+'.dbf'
PACK
ELSE
MESSAGEBOX('В файле ещё нет ни одной настройки',0,m.ErrTitel)
ENDIF
ENDPROC
PROCEDURE ShowMemory
* Показ всех настроек из памяти
LOCAL lnCount, ar(1), i, ErrTitel
ErrTitel = 'CLASS Settings.ShowMemory'
* Получим список имён всех настроек в памяти
* 'B' - свойства созданные с использованием метода AddProperty
lnCount = AMEMBERS(ar,This,0,'B')
IF m.lnCount > 0
CREATE CURSOR (This.Alias+'_Memo') CODEPAGE = 1251 ;
(Name C(20), Type C(1), Value C(50))
FOR i = 1 TO m.lnCount
lcName = ar(i)
luValue = GETPEM(This, m.lcName)
lcValueAsString = This.SerializeValue(m.luValue)
INSERT INTO (This.Alias+'_Memo') (Name, Type, Value) VALUES ;
(lcName, VARTYPE(m.luValue), ;
IIF(AT(VARTYPE(m.luValue),'GOQUX')=0,lcValueAsString,This.ErrSign) )
ENDFOR
GO TOP
BROWSE TITLE 'Настройки в памяти'
USE IN SELECT(This.Alias+'_Memo')
SELECT (This.Alias)
ELSE
MESSAGEBOX('В памяти ещё нет ни одной настройки',0,m.ErrTitel)
ENDIF
ENDPROC
ENDDEFINE
Ratings: 0 negative/2 positive
Re: Сохранить переменную типа Object в файл
lulgu

Сообщений: 1838
Дата регистрации: 30.11.2016
lemenev
Программа представляет для меня не практический, а учебный интерес.
Разве что для любителей потрындеть, а то без ИК совсем затихли, скучновато стало.

ЗЫ. С dbf работают в форме. Пара процедур от ИК останутся в загрузчике, значит должен быть еще и обработчик ошибок.
Тогда и появится смысл возиться с SET-настройками и т.п., их обычно больше сотни.
Для параметров лучше использовать класс EMPTY.

ЗЫ2. Вот и красные художники опять ожили, так что не все еще потеряно ...



Исправлено 2 раз(а). Последнее : lulgu, 20.08.22 22:51
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
PaulWist

Сообщений: 14601
Дата регистрации: 01.04.2004
Например:

PROTECTED PROCEDURE DeserializeValue
...
IF VARTYPE(m.lcValue) <> 'C'
MESSAGEBOX('Свойство для преобразования не символьного типа'+CHR(13)+VARTYPE(m.lcValue),0,m.ErrTitel)
ENDIF
IF VARTYPE(m.lcType) <> 'C'
MESSAGEBOX('Указанный тип преобразования не символьного типа'+CHR(13)+VARTYPE(m.lcType),0,m.ErrTitel)
ENDIF

Если при вызове будет 100500 ошибок, то "упаришься" ОК жать.


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
lulgu

Сообщений: 1838
Дата регистрации: 30.11.2016
PaulWist
Если при вызове будет 100500 ошибок, то "упаришься" ОК жать.

Надо настройки отлаживать, чтобы таких ошибок не было.
А если появятся, то их с первого раза ловят обработчиком ошибок.
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
PaulWist

Сообщений: 14601
Дата регистрации: 01.04.2004
lulgu

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

Ну ка, покажи обработчик ошибок для:

sys(1079)





------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
lulgu

Сообщений: 1838
Дата регистрации: 30.11.2016


И что мне прикажете делать с вашими археологическими раскопками:
2004г, piva
sys(1079,0) - только VFP8 - фокс вылетает с баг репортом - Отладочный вылет

Не пользуйтесь некондицией, только и всего.

ЗЫ. Интересно, а вы сможете продемонстрировать новичку полноценный обработчик ошибок?



Исправлено 1 раз(а). Последнее : lulgu, 22.08.22 00:03
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
Taran

Сообщений: 13623
Откуда: Красноярск
Дата регистрации: 16.01.2008
lemenev
Программа представляет для меня не практический, а учебный интерес, так что любая конструктивная критика по методологии, реализации, оформлению только приветствуется. Для того и публикую.

1.
PROCEDURE Add
* Добавлениие одной настройки в файл
LPARAMETERS luName, luValue

Я всегда пишу так. Так и читается проще. Ну и в других языках так пишется. Вдруг кому код отдать придется или себе.
PROCEDURE Add(luName, luValue)

2.
DO CASE
CASE m.lcType = 'C'
luValue = m.lcValue
CASE m.lcType = 'D'
luValue = CTOD(m.lcValue)
CASE m.lcType = 'L'
luValue = EVALUATE(m.lcValue)
CASE m.lcType = 'N'
luValue = VAL(m.lcValue)
CASE m.lcType = 'T'
nYear = VAL(SUBSTR( m.lcValue, 7, 4 ))
nMonth = VAL(SUBSTR( m.lcValue, 4, 2 ))
nDay = VAL(SUBSTR( m.lcValue, 1, 2 ))
nHours = VAL(SUBSTR( m.lcValue,12, 2 ))
nMinutes = VAL(SUBSTR( m.lcValue,15, 2 ))
nSeconds = VAL(SUBSTR( m.lcValue,18, 2 ))
luValue = DATETIME(nYear, nMonth, nDay, nHours, nMinutes, nSeconds)
CASE m.lcType = 'Y'
* Нужно убрать разделители разрядов
luValue = CAST(STRTRAN(m.lcValue,',','') AS Currency)
ENDCASE

Я бы заменил на следующее. Читабельность и восприятие упрощается, ну и лишнее переменные чтоб не городить.
luValue = icase(m.lcType = 'C', m.lcValue,;
m.lcType = 'D', CTOD(m.lcValue),;
m.lcType = 'L', EVALUATE(m.lcValue),;
m.lcType = 'N', VAL(m.lcValue),;
m.lcType = 'T', DATETIME(VAL(SUBSTR( m.lcValue, 7, 4)),;
VAL(SUBSTR( m.lcValue, 4, 2)),;
VAL(SUBSTR( m.lcValue, 1, 2)),;
VAL(SUBSTR( m.lcValue,12, 2)),;
VAL(SUBSTR( m.lcValue,15, 2)),;
VAL(SUBSTR( m.lcValue,18, 2))),;
m.lcType = 'Y', CAST(STRTRAN(m.lcValue,',','') AS Currency))



Исправлено 2 раз(а). Последнее : Taran, 22.08.22 08:10
Ratings: 0 negative/2 positive
Re: Сохранить переменную типа Object в файл
lemenev

Сообщений: 112
Дата регистрации: 23.06.2022
PaulWist
Например:
PROTECTED PROCEDURE DeserializeValue
...
IF VARTYPE(m.lcValue) <> 'C'
MESSAGEBOX('Свойство для преобразования не символьного типа'+CHR(13)+VARTYPE(m.lcValue),0,m.ErrTitel)
ENDIF
IF VARTYPE(m.lcType) <> 'C'
MESSAGEBOX('Указанный тип преобразования не символьного типа'+CHR(13)+VARTYPE(m.lcType),0,m.ErrTitel)
ENDIF

Если при вызове будет 100500 ошибок, то "упаришься" ОК жать.

Думаю, что это тот редкий случай, когда lulgu прав. Массовые (100500) ошибки в настройках отлаживаются с первого раза и ловятся встроенным обработчиком ошибок.
Другой разговор, нужны ли именно эти две проверки. Дело в том, что функция DeserializeValue вызывается в одном единственном месте, получая данные из файла настроек.
Если такой файл отсутствует, то он создаётся программно с заведомо правильной структурой. И в дальнейшем поля Settings.Value и Settings.Type – символьного типа.
Т.е. надобность в этих проверках может возникнуть, если предположить следующий сценарий: файл Settings подменяется другим, имеющим поля Value и Type, но не символьного типа. И из этого нового файла пытаются загрузить настройки. Думаю, что вероятность такого крайне мала. Но я перестраховался.
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
lemenev

Сообщений: 112
Дата регистрации: 23.06.2022
Taran
Я всегда пишу так. Так и читается проще. Ну и в других языках так пишется. Вдруг кому код отдать придется или себе.

Спасибо за практические рекомендации по стилю программирования. Особенно понравилась замена конструкции CASE на функцию ICASE.
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
Taran

Сообщений: 13623
Откуда: Красноярск
Дата регистрации: 16.01.2008
Дабы избежать массовых ошибок и вызова 100500 messagebox

PROCEDURE LoadSettings
SELECT 0
USE Settings
LOCAL lcName, luValue
SCAN ALL
lcName = This.CheckName(Settings.Name)
if This.DeserializeValue(Settings.Value, Settings.Type, @luValue)
This.AddProperty(m.lcName, m.luValue)
else
exit
endif
ENDSCAN
USE IN SELECT("Settings")
ENDPROC


PROTECTED PROCEDURE DeserializeValue(lcValue, lcType, luValue)
LOCAL ErrTitel, lError
ErrTitel = 'CLASS Settings.DeserializeValue'
LOCAL nYear, nMonth, nDay, nHours, nMinutes, nSeconds
IF VARTYPE(m.lcValue) <> 'C'
MESSAGEBOX('Свойство для преобразования не символьного типа'+CHR(13)+VARTYPE(m.lcValue),0,m.ErrTitel)
return FALSE
ENDIF
IF VARTYPE(m.lcType) <> 'C'
MESSAGEBOX('Указанный тип преобразования не символьного типа'+CHR(13)+VARTYPE(m.lcType),0,m.ErrTitel)
return FALSE
ENDIF
lcValue = TRIM(m.lcValue)
TRY
DO CASE
CASE m.lcType = 'C'
luValue = m.lcValue
CASE m.lcType = 'D'
luValue = CTOD(m.lcValue)
CASE m.lcType = 'L'
luValue = EVALUATE(m.lcValue)
CASE m.lcType = 'N'
luValue = VAL(m.lcValue)
CASE m.lcType = 'T'
nYear = VAL(SUBSTR( m.lcValue, 7, 4 ))
nMonth = VAL(SUBSTR( m.lcValue, 4, 2 ))
nDay = VAL(SUBSTR( m.lcValue, 1, 2 ))
nHours = VAL(SUBSTR( m.lcValue,12, 2 ))
nMinutes = VAL(SUBSTR( m.lcValue,15, 2 ))
nSeconds = VAL(SUBSTR( m.lcValue,18, 2 ))
luValue = DATETIME(nYear, nMonth, nDay, nHours, nMinutes, nSeconds)
CASE m.lcType = 'Y'
* Нужно убрать разделители разрядов
luValue = CAST(STRTRAN(m.lcValue,',','') AS Currency)
ENDCASE
CATCH TO lError
MESSAGEBOX('Ошибка в данных значения свойства'+CHR(13)+m.lcValue,0,m.ErrTitel)
luValue = This.ErrSign
return FALSE
ENDTRY
IF VARTYPE(m.luValue) <> Type
MESSAGEBOX('Несоответствие указанного типа и типа данных значения'+;
' свойства'+CHR(13)+Type+' и '+m.lcValue,0,m.ErrTitel)
luValue = This.ErrSign
return FALSE
ENDIF
RETURN TRUE
ENDPROC
Ratings: 0 negative/0 positive
Re: Сохранить переменную типа Object в файл
Taran

Сообщений: 13623
Откуда: Красноярск
Дата регистрации: 16.01.2008
Для избежания вставок в коде CHR(13) и прочих...
Создай файл типа Consts.H
#DEFINE CR CHR(13)
#DEFINE LF CHR(10)
#DEFINE CRLF CHR(13)+CHR(10)
#DEFINE SP CHR(32)
#DEFINE NoBreakSP CHR(160)
#DEFINE TAB CHR(9)
Со временем этот файл будет расти.
И своё ФИО там пропишешь и почту и многое чего еще.

И в первых строка файлов PRG вставляй
#INCLUDE Consts.H

У меня в главном файле H примерно 170 строк.
А в некоторых проектах до десятка файлов H включено в проект.

К визуальным классам тоже можно прицепить.
Ratings: 0 negative/1 positive
Re: Сохранить переменную типа Object в файл
Taran

Сообщений: 13623
Откуда: Красноярск
Дата регистрации: 16.01.2008
Ты несколько проигнорил/непонял весь потенциал объявления функции со скобками.

Приведенный мной выше пример
PROTECTED PROCEDURE DeserializeValue(lcValue, lcType, luValue)

более правильно расписать так.
PROTECTED PROCEDURE DeserializeValue(lcValue as String, lcType as String, luValue as Variant @) as Logical
если тип принимаемого значения ясны из именования по венгерской нотации.
То вот третий параметр без указания @ не понятно что должен в этой переменной вернуть новое значение.
Хоть будет работать если и не указывать. Главное в вызывающем коде указать @ перед именем переменной.
Ну и завершить наименованием метода объявлением типа возвращаемого значения офигенная вещь.
Т.е. глядя только на название метода и видя возвращаемый тип, тебе уже многое ясно и не надо просматривать весь код.
Естественно при малом коде она не столь эффективна.
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 23 (Гостей: 23)

© 2000-2024 Fox Club 
Яндекс.Метрика