Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Компоненты";
Текущий архив: 2006.11.19;
Скачать: [xml.tar.bz2];

Вниз

работа в рантайме с классами (не обьектами)   Найти похожие ветки 

 
sirin ©   (2006-03-26 15:53) [0]

Здраствуйте. Подсткажите, есть ли в делфи возможность динамического формирования класса ?
Я хочу создать класс в рантайме, добавить ему поля, и свойства, и создать с него обьект
Это нужно для создания обьектных оберток вокруг датасета.


 
Наиль ©   (2006-03-26 20:33) [1]

Нет


 
Джо ©   (2006-03-26 20:36) [2]

> sirin ©   (26.03.06 15:53)

А как ты его потом собираешься использовать, если на момент компиляции имена этих методов и полей неизвестны?


 
sirin ©   (2006-03-26 20:52) [3]

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


 
Джо ©   (2006-03-26 21:12) [4]

> [3] sirin ©   (26.03.06 20:52)
> Неужели непредусмотрена
> возможность динамического добавления свойств ?

Нет. Вся эта run-time type information формируется при компиляции.


 
Джо ©   (2006-03-26 21:57) [5]

Могу предложить такую схему.

[CODE]
unit CustStorage;

interface
uses SysUtils, Classes, Contnrs;

type

 EWrongDataType = class (Exception);

 TDataType = (dtString,dtInteger,dtFloat);

 TCustomData = class
 private
   FStringValue: string;
   FIntegerValue: Integer;
   FFloatValue: Double;
   FDataType: TDataType;
   FName: string;
   function GetAsFloat: Double;
   procedure SetAsFloat(const Value: Double);
   function GetAsInteger: Integer;
   procedure SetAsInteger(const Value: Integer);
   function GetAsString: string;
   procedure SetAsString(const Value: string);
   procedure RaiseIfNotType (AType: TDataType);
 public
   property Name: string read FName;
   property AsString: string read GetAsString write SetAsString;
   property AsInteger: Integer read GetAsInteger write SetAsInteger;
   property AsFloat: Double read GetAsFloat write SetAsFloat;
   property DataType: TDataType read FDataType;
   constructor Create (ADataType: TDataType; AName: string);
 end;

 TCustomStorage = class
 private
   FList: TObjectList;
   function GetItems(AName: string): TCustomData;
   function FindItem (AName: string): Integer;
   procedure Add (AName: string; DataType: TDataType; Value: Variant);
 public
   constructor Create;
   destructor Destroy; override;
   property Items[AName: string]: TCustomData read GetItems; default;
   procedure AddInteger (AName: string; AValue: Integer);
   procedure AddString (AName: string; AValue: string);
   procedure AddFloat (AName: string; AValue: Double);    
 end;

implementation
uses TypInfo;

constructor TCustomData.Create(ADataType: TDataType; AName: string);
begin
 FDataType := ADataType;
 FName := AnsiUpperCase(AName);
end;

function TCustomData.GetAsFloat: Double;
begin
 RaiseIfNotType(dtFloat);
 Result := FFloatValue;
end;

function TCustomData.GetAsInteger: Integer;
begin
 RaiseIfNotType(dtInteger);
 Result := FIntegerValue;
end;

function TCustomData.GetAsString: string;
begin
 RaiseIfNotType(dtString);
 Result := FStringValue;
end;

procedure TCustomData.RaiseIfNotType(AType: TDataType);
begin
 if AType <> FDataType then
   raise EWrongDataType.CreateFmt("Wrong data type: %s",[GetEnumName(TypeInfo(TDataType),Integer(AType))]);
end;

procedure TCustomData.SetAsFloat(const Value: Double);
begin
 RaiseIfNotType(dtFloat);
 FFloatValue := Value
end;

procedure TCustomData.SetAsInteger(const Value: Integer);
begin
 RaiseIfNotType(dtInteger);
 FFloatValue := Value
end;

procedure TCustomData.SetAsString(const Value: string);
begin
 RaiseIfNotType(dtString);
 FStringValue := Value
end;

{ TCustomStorage }

procedure TCustomStorage.Add(AName: string; DataType: TDataType;
 Value: Variant);
var
 Idx: Integer;
 Data: TCustomData;
begin
 Idx := FindItem(AName);
 if Idx = -1 then
 begin
   Data := TCustomData.Create(DataType,AName);
   case DataType of
     dtString: Data.AsString := Value;
     dtInteger: Data.AsInteger := Value;
     dtFloat: Data.AsFloat := Value;
   end;
   FList.Add(Data)
 end
 else
   raise Exception.CreateFmt("Item "%s" already exists",[AName]);
end;

procedure TCustomStorage.AddFloat(AName: string; AValue: Double);
begin
 Add (AName,dtFloat,AValue);
end;

procedure TCustomStorage.AddInteger(AName: string; AValue: Integer);
begin
 Add (AName,dtInteger,AValue);
end;

procedure TCustomStorage.AddString(AName, AValue: string);
begin
 Add (AName,dtString,AValue);
end;

constructor TCustomStorage.Create;
begin
 FList := TObjectList.Create (True);
end;

destructor TCustomStorage.Destroy;
begin
 FList.Free;
 inherited;
end;

function TCustomStorage.FindItem(AName: string): Integer;
var
 I: Integer;
begin
 Result := -1;
 AName := AnsiUpperCase(AName);

 for I := 0 to FList.Count - 1 do
   if TCustomData(FList[I]).Name = AName then
   begin
     Result := I;
     Break
   end
end;

function TCustomStorage.GetItems(AName: string): TCustomData;
var
 Idx: Integer;
begin
 Idx := FindItem(AName);
 if Idx = -1 then
   raise Exception.CreateFmt("Item "%s" not found",[AName])
 else
   Result := TCustomData(FList[Idx])
end;

end.[/CODE]

Пример использования.
[CODE]
uses CustStorage;

procedure TForm18.Button1Click(Sender: TObject);
var
 AStorage: TCustomStorage;

 IntegerField: Integer;
 StringField: string;
 FloatField: Double;
begin
 AStorage := TCustomStorage.Create;
 try
   AStorage.AddInteger("MyIntegerField"); // не указываем значение сразу
   AStorage.AddString("MyStringField","строка");
   AStorage.AddFloat("MyFloatField",999.666);

   AStorage["MyIntegerField"].AsInteger := 123; // задаем значение

   IntegerField := AStorage["MyIntegerField"].AsInteger;
   StringField := AStorage["MyStringField"].AsString;
   FloatField := AStorage["MyFloatField"].AsFloat;

 finally
   AStorage.Free;
 end;
end;[/CODE]

--
Просто пример, его можно улучшить и даже упростить. В нем, возможно, есть ошибки: написал наспех и особо не тестировал.


 
Джо ©   (2006-03-26 21:58) [6]

Сорри, напутал с тэгами, чертов BB CODE :(


 
Джо ©   (2006-03-26 22:00) [7]

Явно не мой день. :( Исправить метод:

procedure TCustomData.SetAsInteger(const Value: Integer);
begin
RaiseIfNotType(dtInteger);
FIntegerValue := Value
end;

В общем, я думаю, суть того, что я предложил, ясна.


 
sirin ©   (2006-03-27 00:30) [8]

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


 
Джо ©   (2006-03-27 00:59) [9]

> [8] sirin ©   (27.03.06 00:30)

Честно говоря, я не вполне понимаю, что вы имеете ввиду под "объектные обертки вокруг датасетов".



Страницы: 1 вся ветка

Форум: "Компоненты";
Текущий архив: 2006.11.19;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.48 MB
Время: 0.054 c
1-1160488144
Dush
2006-10-10 17:49
2006.11.19
VB в Delphi (AndAlso и OrElse)


2-1162490522
nordic3
2006-11-02 21:02
2006.11.19
Перерисовка Image


8-1144670277
Acidlex
2006-04-10 15:57
2006.11.19
Измерение уровня сигнала с микрофона и линейного входа


2-1162203111
Still Swamp
2006-10-30 13:11
2006.11.19
Как получиьт разницу времени локального и GMT


2-1162383035
Владимир71
2006-11-01 15:10
2006.11.19
РАЗМЕР ПОЛЯ





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский