![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
||||
|
||||
|
Есть задача создать класс для подгрузки (из БД или ИНИ) настроек и дальнейшего их использования в программе. Причем для более удобного использования этого класса, вид извлечения и добавления этих настроек должен выглядеть вот так:
Код:
var
Opt:TMyClass; //экземпляр класса
Var1:integer;
begin
Opt := TMyClass.Create;
Opt['Category']['SubCategory']['SubSubCategory']['Option1'] := 'qwe';
{Строчка выше означает, что класс должен создать (если ранее не создано) категорию 'Category',
в ней Подкатегорию 'SubCategory', в ней еще подкатегорию 'SubSubCategory' (то есть все в виде дерева),
в ней опцию 'Option1' и присвоить этой опции значение 'qwe'}
Var1 := Opt['Category']['Option2'];
{Строчка выше означает, что переменной Var1 типа integer должно присвоиться значение опции 'Option2'
из категории 'Category', если данные опция и категория созданы
}
end;То есть при первом же рассмотрении встает вопрос, как сделать так, чтобы у дефолтной property функции для read и write имели разные типы данных? Типа того: Код:
TCategory = Class; TMyClass = Class private function GetV(Name:string):TCategory; procedure SetV(Name:string;Value:STRING); public property Cat[Name:string]:TCategory read GetV write SetV; default; end; |
|
#2
|
|||
|
|||
|
похожее делал так:
Код:
procedure InitIni;
begin
inimap := TiniManager.Create('ini.ini')
inimap.define('section', 'somevar', '100', TInt.Create(@intvar));
inimap.define('section', 'somevar2', 'default', TStr.Create(@strvar));
inimap.define('section', 'somevar3', 'yes', TBool.Create(@boolvar));
inimap.define('main', 'form-x', '100', TProp.Create(Form1, 'left'));
inimap.define('main', 'form-y', '100', TProp.Create(Form1, 'top'));
end;
inimap.write;
inimap.read;хотя TProp.Create(...) можно заменить разными версиями метода .define Последний раз редактировалось Pyro, 08.02.2013 в 09:56. |
|
#3
|
||||
|
||||
|
Что? Где в вашем сообщении ответ на мой вопрос?
|
|
#4
|
|||
|
|||
|
variant пробовал?
|
|
#5
|
||||
|
||||
|
А разве в варианте можно хранить экземпляр класса? Даже если и можно, я не смогу обращаться с переменной типа вариант, как с экземпляром класса. Ну разве что делать так:
with opt['Category'] as TCategory with ['SubCategory'] as TCategory **** И так далее. А должно выглядеть так, как я написал в первом сообщении. Цель - сделать программу легко перевариваемую программистами, чтобы один мог написать, другой подправить. Уже наделал кучу классов для красивого кодинга в дальнейшем. Споткнулся вот на этом. |
|
#6
|
|||
|
|||
|
вот такие варианты есть
Код:
Var1 := Opt['Category','Option2'];
Var1 := Opt['Category']['Option2'].get
Var0 := Opt['Category','Sub'].get('Option1');
with Opt['Category','Sub'] do
begin
Var1 := get('Option2')
Var2 := get('Option3')
endа предыдущий код который я выкладывал - для того что бы избавиться от дублирования при записи/чтении Последний раз редактировалось Pyro, 11.02.2013 в 09:03. |
|
#7
|
||||
|
||||
|
Код:
Var1 := Opt['Category','Option2'];
Var1 := Opt['Category']['Option2'].get
Var0 := Opt['Category','Sub'].get('Option1');
with Opt['Category','Sub'] do
begin
Var1 := get('Option2')
Var2 := get('Option3')
endЭто не то, что я хотел, но пока будет так. Во всяком случае, если мне удастся сделать то, что я задумал (переделать класс), то это никак не повлияет на уже написанный код с использованием данного класса. Так что вопрос остается открытым. Пока что обращение к классу выглядит так: Код:
var Var1:string; Var2:integer; Opt:TMyClass; Begin Opt:=TMyClass.Create; Opt['Category']['SubCategory']['Option1']:=5; Opt['Category']['SubCategory']['Option2']:=6; Opt['Category']['SubCategory']['Option3']:='qwe'; Var1:=Opt['Category']['SubCategory']['Option3'][1]; Var2:=Opt['Category']['SubCategory']['Option2'] - Opt['Category']['SubCategory']['Option1']; end; Var2 = 1 То есть средствами класса определяются нужные типы данных (принимаются и возвращаются не variant, а именно string или integer или real, в зависимости от типа переменной, в которую считывается или из которой записывается). Не получается лишь сделать путь к опции в виде правильного Х-уровневого дерева. То есть для сей конструкции есть класс Опции, в котором хранится экземпляр класса Категории, в нем экземпляр класса Подкатегории, а в нем уже екземпляр класса Настройки. Если захочу сделать больше подкатегорий, то придется делать дополнительные классы для них. Если завяжу класс категории сам на себя, то не смогу в нужный момент извлечь таким же способом опцию (точнее смогу, только способом .get('Option1'), а мне надо дефолтной property, но в дефолтной property уже будет стоять ссылка на класс категорий). Вот такие дела... |
|
#8
|
||||
|
||||
|
Еще можно сделать обращение вида:
Opt['Category/SubCategory/SubSubCategory/Option'], но это не красиво выглядит. Еще можно было бы сделать так: Opt['Category','SubCategory',........,'Option1'] То есть переменным числом параметров, но я не знаю как это сделать. Так же работает функция Write/Writeln (и еще некоторые функции) - принимает любое количество параметров, но я не могу понять, как это реализовано. |
|
#9
|
|||
|
|||
|
Может небольшая редакция требований спасет отца русской демократии:
Код:
Opt['Category']['SubCategory']['Option1'].Value:=5; ... Var1:=Opt['Category']['SubCategory']['Option3'][1].Value; |
|
#10
|
||||
|
||||
|
Цитата:
|
|
#11
|
|||
|
|||
|
Цитата:
Код:
например intvar := Edit1 Цитата:
Код:
Opt(a: array of string) ... Opt(['Category','SubCategory',........,'Option1']) Последний раз редактировалось Pyro, 11.02.2013 в 13:46. |
|
#12
|
||||
|
||||
|
Цитата:
Цитата:
|
|
#13
|
|||
|
|||
|
в старших дельфях можно так попробовать:
Код:
type
TMyClass = record // хз работает ли на классах
class operator Implicit(a: Integer): TMyClass; //запись?
class operator Implicit(a: TMyClass): Integer; //чтение? |
|
#14
|
||||
|
||||
|
сделай уже что б хоть как-то работало:
Код:
MyObj['Category\SubCategory\Option'] := '123'; v := MyObj['Category\SubCategory\Option']; Код:
MyObj.Category.SubCategory.Option := '123'; v := MyObj.Category.SubCategory.Option; |
|
#15
|
||||
|
||||
|
Цитата:
with MyObj['Category\SubCategory'] А опций может быть много... Цитата:
MyObj['Globals'].... MyObj['Locals']['Interface']['MainForm']['Top']... MyObj['Locals']['Interface']['MainForm']['Left']... ну и так далее То есть класс должен быть универсален, а не заточен под конкретное приложение. |