« Поставить закладку » « Сделать стартовой »

« Форумы » « Блоги » « Статьи » « Новости » « Файлы » « Realcoding IRC » « Site map » « Поиск »


Главная Главная
Анонсы Анонсы
Форумы Форумы
Каталог Каталог
Поиск Поиск
Опросы Опросы
Книжный магазин Книжный магазин
Реклама на сайте
Публикации Публикации
Партнеры Партнеры
Карта Карта сайта
Рассылки Рассылки
RSS экспорт
Настройки Настройки
О нас пишут О нас пишут
Контакты Контакты
Гостевая книга Гостевая книга


ПнВтСрЧтПтСбВс
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
    Популярное
Практический JS: оптимизируем CSS expressions

Как создать простой текст любой сложности: взаимодействие Microsoft Office 2007 + Mind Маnager

Работа с буфером обмена

Функция AccessResource

Prototype: селекторы и события

1. Введение

Как же выключить компьютер в Windows XP ?

Функция SetClassWord

Версионная эпидемия Visual Studio 2005

авторизация+аутентификация без куки


    Архив файлов



    Сообщества



    Документация

Статьи:: Delphi :: Разные статьи :: Сохранение и загрузка данных в объекты на примере коллекций.


отправить ссылку другу версия для печати  Обсудить на форуме

Сохранение и загрузка данных в объекты на примере коллекций.



RTTI в действии

Сохранение и загрузка данных в объекты на примере коллекций.

Если в Вашей программе используются классы для описания объектов некоторой предметной области, то данные, их инициализирующие, можно хранить и в базе данных. Но можно выбрать гораздо более продуктивный подход, который доступен в Delphi/C++ Builder. Среда разработки Delphi/C++ Builder хранит ресурсы всех форм в двоичных или текстовых файлах и эта возможность доступна и для разрабатываемых с ее помощью программ. В данном случае, для оценки удобств такого подхода лучше всего рассмотреть конкретный пример.

 

Необходимо реализовать хранение информации о некоей службе рассылки и ее подписчиках. Будем хранить данные о почтовом сервере и список подписчиков. Каждая запись о подписчике хранит его личные данные и адрес, а также список тем(или каталогов), на которые он подписан. Как большие поклонники Гради Буча (Grady Booch), а также будучи заинтересованы в удобной организации кода, мы организуем информацию о подписчиках в виде объектов. В Delphi для данной задачи идеально подходит класс TCollection, реализующий всю необходимую функциональность для работы со списками типизированных объектов. Для этого мы наследуемся от TCollection, называя новый класс TMailList - список рассылки, а также создаем наследника от TCollectionItem - TMailClient - адресат рассылки. Последний будет содержать все необходимые данные о подписчике, а также реализовывать необходимые функции для работы с ним.

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

 

type 
  TMailClient = class(TCollectionItem) 
  private 
    FName: string; 
    FAddress: string; 
    FEnabled: boolean; 
    FFolders: TStringList; 
  public 
    Files: TStringList;  // список файлов к рассылке. заполняется в run-time. Сохранению не подлежит  
    constructor Create(Collection: TCollection); override; 
    destructor Destroy; override; 
    procedure PickFiles; 
  published 
    property Name: string read FName write FName;  // имя адресата 
    property Address: string read FAddress write FAddress; // почтовый адрес 
    property Enabled: boolean read FEnabled write FEnabled default true;
    property Folders: TStringList read FFolders write FFolders; // список папок (тем) подписки 
  end; 


Класс содержит сведения о имени клиента, его адресе, его статусе(Enabled), а также список каталогов, на которые он подписан. Процедура PickFiles составляет список файлов к отправке и сохраняет его в свойстве Files
Класс TMailList, хранящий объекты класса TMailClient, приведен ниже.

 

  TMailList = class(TCollection) 
  public 
    function GetMailClient(Index: Integer): TMailClient; 
    procedure SetMailClient(Index: Integer; Value: TMailClient); 
  public 
    function  Add: TMailClient; 
    property Items[Index: Integer]: TMailClient read GetMailClient  write SetMailClient; default; 
  end; 

Теперь поместим класс TMailList в класс TMailer. В него можно будет потом включить данные о параметрах доступа к почтовому серверу для отправки почты. Он мог бы и отправлять почту, но в данном примере это не использовано, дабы не перегружать код.
 

То есть в нашем примере он выполняет только роль носителя данных о подписчиках и их подписке. Класс TComponent, от которого он наследуется можно сохранить в файл, в то время как TCollection самостоятельно не сохранится. Только если она агрегирована в TComponent. Именно это у нас и реализовано.

 

  TMailer = class(TComponent) 
  private 
    FMailList: TMailList; 
  public 
    constructor Create(AOwner: TComponent); override; 
    destructor Destroy; override; 
  published 
    property MailList: TMailList read FMailList write FMailList; // коллекция - список рассылки. 
    // здесь можно поместить, к примеру, данные о соединении с почтовым сервером  
  end; 


Повторюсь. В данном случае мы наследуемся от класса TComponent, для того, чтобы была возможности записи данных объекта в файл. Свойство MailList содержит уже объект класса TMailList.
Реализация всех приведенных классов приведена ниже.

 

constructor TMailClient.Create(Collection: TCollection); 
begin 
  inherited; 
  Folders := TStringList.Create; 
  Files := TStringList.Create; 
  FEnabled := true; 
end; 
 
destructor TMailClient.Destroy; 
begin 
  Folders.Free; 
  Files.Free; 
  inherited; 
end; 

// здесь во всех каталогах Folders ищем файлы для рассылки и помещаем их в Files. 
procedure TMailClient.PickFiles; 
var i: integer;
begin 
    for i:=0 to Folders.Count-1 do CreateFileList(Files, Folders[i]); 
end; 

// Стандартный код при наследовании от класса коллекции: переопределяем тип  
function TMailList.GetMailClient(Index: Integer): TMailClient; 
begin 
  Result := TMailClient(inherited Items[Index]); 
end; 
 
// Стандартный код при наследовании от класса коллекции  
procedure TMailList.SetMailClient(Index: Integer; Value: TMailClient); 
begin 
  Items[Index].Assign(Value); 
end; 

 // Стандартный код при наследовании от класса коллекции: переопределяем тип  
function TMailList.Add: TMailClient; 
begin 
  Result := TMailClient(inherited Add); 
end; 

// создаем коллекцию адресатов рассылки TMailList 
constructor TMailer.Create(AOwner: TComponent); 
begin 
  inherited Create(AOwner); 
  MailList := TMailList.Create(TMailClient); 
end; 
 
destructor TMailer.Destroy; 
begin 
  MailList.Free; 
  inherited; 
end; 
//--------------------- 
 

Функция CreateFileList создает по каким-либо правилам список файлов на основе переданного ей списка каталогов, обходя их рекурсивно. К примеру, она может быть реализована так.

 

procedure CreateFileList(sl: TStringList; const FilePath: string); 
var 
  sr: TSearchRec; 
  procedure ProcessFile; 
  begin 
    if (sr.Name = '.')or(sr.Name = '..') then exit; 
    if sr.Attr <> faDirectory then 
      sl.Add(FilePath + '' + sr.Name); 
    if sr.Attr = faDirectory then 
    begin 
      CreateFileList(sl, FilePath + '' + sr.Name); 
    end; 
  end; 
begin 
  if not DirectoryExists(FilePath) then exit; 
  if FindFirst(FilePath + '' + '*.*', faAnyFile , sr) = 0 then ProcessFile; 
  while FindNext(sr) = 0 do ProcessFile; 
  FindClose(sr); 
end; 

В итоге мы располагаем классом TMailer, содержащим всю необходимую нам информацию. Теперь перейдем к созданию объекта, их сохранению и загрузке.

 

var 
  Mailer: TMailer; // это наш объект для хранения данных о почтовой рассылки
  
// Процедура загрузки данных в объект. Может быть процедурой OnCreate() главной формы.
procedure TfMain.FormCreate(Sender: TObject);
var 
  sDataFile, sTmp: string; 
  i, j: integer;
begin 
 
  Mailer := TMailer.Create(self); 
 
 // будем считать, что данные были сохранены в файл users.dat в каталоге программы
  sDataFile := ExtractFilePath(ParamStr(0)) + 'users.dat'; 
 
  //...загрузка данных из файла 
  if FileExists(sDataFile) then
    LoadComponentFromTextFile(Mailer, sDataFile); 
   { здесь данные из файла загружены }

  //...перебор подписчиков 
  for i:=0 to Mailer.MailList.Count-1 do 
  begin 

    sTmp := Mailer.MailList[i].Name;  //...обращение к имени 
    sTmp := Mailer.MailList[i].Address; //...обращение к адресу 
    //... sTmp - фиктивная переменная. Поменяйте ее на свои.  
	
    Mailer.MailList[i].PickFiles;  //... поиск файлов для отправки очередному подписчику. 
 
   //...перебор найденных файлов к отправке 
    for j:=0 to Mailer.MailList[i].Files.Count-1 do 
    begin 
      sTmp := Mailer.MailList[i].Files[j]; 
    end;
	
  end;
end;

После загрузки данных мы можем работать с данными в нашей коллекции подписчиков. Добавлять и удалять их ( Mailer.MailList.Add; Mailer.MailList.Delete(Index); ). При завершении работы программы необходимо сохранить уже новые данные в тот же файл.

// Процедура сохранения данных из объекта в файл. Может быть процедурой OnDestroy() главной формы.
procedure TfMain.OnDestroy;
begin
  //...сохранение данных в файл users.dat
  SaveComponentToTextFile(Mailer, ExtractFilePath(ParamStr(0)) + 'users.dat'); 
end;

Хранение данных в файле позволяет оказаться от использования БД, если объем данных не слишком велик и нет необходимости в совместном доступе к данным.
Самое главное - мы организуем все данные в виде набора удобных для работы классов и не тратим время на их сохранение и инициализацию из БД.
Приведенный пример лишь иллюстрирует этот подход. Для его реализации могут подойти и 2 таблицы в БД. Однако приведенный подход удобен при условии, что данные имеют сложную иерархию. К примеру, вложенные коллекции разных типов гораздо сложнее разложить в базе данных, для их извлечения потребуется SQL. Решайте сами, судя по своей конкретной задаче.

Далее приведен код функций для сохранения/чтения компонента.

 

 
//...процедура загружает(инициализирует) компонент из текстового файла с ресурсом 
procedure LoadComponentFromTextFile(Component: TComponent; const FileName: string); 
var 
  ms: TMemoryStream; 
  fs: TFileStream; 
begin 
  fs := TFileStream.Create(FileName, fmOpenRead); 
  ms := TMemoryStream.Create; 
  try 
    ObjectTextToBinary(fs, ms); 
    ms.position := 0; 
    ms.ReadComponent(Component); 
  finally 
    ms.Free; 
    fs.free; 
  end; 
end; 
 
//...процедура сохраняет компонент в текстовый файл 
procedure SaveComponentToTextFile(Component: TComponent; const FileName: string); 
var 
  ms: TMemoryStream; 
  fs: TFileStream; 
begin 
  fs := TFileStream.Create(FileName, fmCreate or fmOpenWrite); 
  ms := TMemoryStream.Create; 
  try 
    ms.WriteComponent(Component); 
    ms.position := 0; 
    ObjectBinaryToText(ms, fs); 
  finally 
    ms.Free; 
    fs.free; 
  end; 
end; 




Рубрика: Разные статьи




XML документация в C#.

XML в .NET

Сегодня речь пойдет об одной интересной и полезной возможности языка С#, которая поможет нам в документировании кода. Она называется «XML документация» или «Документирующие комментарии XML». Это такие специальные теги XML, которые содержаться в комментариях и описывают свойства или методы в конкретном файле. Так вот, есть по крайней мере три веских причины, почему всегда следует заполнять XML комментарии.


Подробнее... | Рубрика: XML в .NET | Добавлено: 08.10.2008

Курсоры в MySQL 5.

MySQL

Начиная с 5-ой версии, MySQL имеет возможность создавать курсоры. Курсор — это виртуальная таблица, предоставляющая альтернативный способ просмотра табличных данных. Курсор не содержит данных, а лишь ссылается на них из других таблиц. Из этого вытекает ряд особенностей, но об этом ниже.


Подробнее... | Рубрика: MySQL | Добавлено: 08.10.2008

Microsoft опубликовала подробности о сессиях Windows 7.

Мероприятия

В преддверии конференции WinHEC компания Microsoft опубликовала подробный список сессий, которые пройдут в рамках конференции. Довольно-таки большое количество выступлений будет посвящено Windows 7, что не может не радовать. Принимая во внимание тот факт, что PDC и WinHEC разделяют несколько дней, а пройдут они в одном здании - Los Angeles Convention Center, - можно несколько дней поиграть в прятки, спрятавшись в какой-нибудь комнате, но зато бесплатно посетить WinHEC.


Подробнее... | Рубрика: Мероприятия | Добавлено: 08.10.2008

Остальные статьи:

Microsoft делится подробностями о том, что будет после Windows
Тестируем новый javascript от нового браузера Google
MySQL Query Cache
Использование провайдеров компиляции в Asp.net
Чего мы ждем от C# 4.0
Delphi 2009 и C++Builder 2009
Джоэл Спольски и Джеф Этвуд запустили новый вебсайт для программистов - StackOve...
Поиск кода Google /* что нового? */
10 jQuery скриптов для улучшения интерфейса
Генераторы отчетов FastReport 4 и QuickReport 5: версии 2008 года
День программиста — набор стерeотипов
Индусские програмисты
Вышел Django 1.0
Портативная версия Google Chrome Portable
Исходные коды .Net Frameword 3.5 SP1 для отладки в Visual Studio
Пишем правильный online WYSIWYG-редактор


Цитата дня (все,добавить):

Портал фрилансеров

    Рубрикатор

Программирование

C/С++
Обучение
Windows API
XAML
Моделирование
Паттерны
Visual Basic 7 .NET
WxWidgets
Функции WinApi
Функции С++
Разработка под Mac OS
Eiffel
Visual Studio 2008
UI дизайн
Алгоритмы
Конкурсные статьи
Turbo Pascal
Visual Studio
CASE-средства
Visual Studio 2005
Без VCL
Delphi
Тех. документация
Тестирование
Software Testing
ООП
TCP/IP
Google Android
Windows Installer
.NET Framework
Драйвера
C# C Sharp
Справка
Проектирование
Информ. системы
Visual Basic
Assembler
Оптимизация кода
Gtk+
Компоненты
Реинжиниринг
Управление проектами
Extreeme programming
Lotus Notes
Алгебраическое проектирование

Интернет технологии

PHP
Perl
ASP
WAP
Cookies
SSI
CGI
Web Servers
VB Script
DNS
CSS
XML
Html
Java Script
Java2ME
Firewall
Flash
.htaccess
Apache
VRML
Протоколы
Поисковые системы
Технология JAVA
Учебник по PHP
Учебник по JavaScript
Учебник по XML
Java Q&A
AJAX
DHTML
XHTML
Dreamweaver
Web 2.0
Python
Вебмастеру
Cisco
Ruby on Rails
Silverlight

Базы данных

Access
InterBase
MySQL
Oracle
ADO .NET
Основы SQL
Учебник по Access 2002
MS
Microsoft FoxPro
Доступ к данным
XML в MS SQL Server 2000
ODBC и MyODBC
Обучение
Caché
DB2
PostgresSQL
Sybase
Теория
Хранилища данных
Безопасность
Реляционные данные
MySQL и mSQL

Остальное:

Разное
Обзоры книг
Безопасность
Графика и дизайн
Юмор
Linux
Фракталы
Microsoft Axapta
Многоядерность
Сети
Microsoft Office
Работа
MS-DOS
Криптография
Графика и игроделание
Новости SDK
Системы защиты
Учебник по AutoCad
CVS
Windows XP
Windows Server 2003
Windows Vista
Windows 7
Мероприятия

    Кто на сайте
Вы не зарегистрированы.
Имя:

Пароль:

Запомнить

Регистрация позволит Вам пользоваться дополнительными сервисами.
Сейчас на сайте:
Гостей: 147
Пользователей: 0