Автоматическое обнаружение единиц в проекте для пакета пользовательского компонента
Если вы разрабатываете пакет для пользовательского компонента, который позволяет включать многочисленные предварительно написанные единицы в проект, явно предназначенные для работы с этим пользовательским компонентом, или писать свои собственные для выполнения той же функции, как и одна из существующих, вы, вероятно, столкнулись с проблемой обнаружения этих единиц в проекте.
В статье рассматривается проблема автоматического обнаружения единиц в проекте, использующих ваш пакет, и предлагаются решения для этой проблемы.
Описание проблемы
Пользовательский компонент, реализованный в пакете, имеет свойство PluginIndex, которое соответствует одному из "плагинов", зарегистрированных в глобальном списке. Каждая "плагин"-единица имеет инициализационный раздел, который регистрирует этот класс в глобальном списке. Проблема заключается в том, что поскольку компонент реализован в пакете (и установлен в IDE), а "плагин"-единицы используются в другом проекте, пакет не обнаруживает присутствие этих единиц, и пользовательский компонент не может получить доступ к глобальному списку, так как он находится в совершенно другом контексте.
Подтвержденный ответ
Одним из решений этой проблемы может быть использование издателя свойств пользовательского компонента. Издатель свойств - это пользовательский компонент, который отображается в редакторе свойств компонента в IDE. Вы можете использовать издатель свойств для отображения списка доступных "плагинов" и выбора одного из них в качестве значения свойства PluginIndex.
Вот пример кода, который демонстрирует, как создать издателя свойств для пользовательского компонента в Object Pascal (Delphi):
unit PluginEditor;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;
type
TPluginEditor = class(TObject)
private
FComponent: TComponent;
FEditor: TComboBox;
public
constructor Create(Component: TComponent);
destructor Destroy; override;
property Component: TComponent read FComponent;
property Editor: TComboBox read FEditor;
function GetProperties(Props: TStrings): Boolean;
function Execute: Boolean;
end;
implementation
constructor TPluginEditor.Create(Component: TComponent);
begin
inherited Create;
FComponent := Component;
FEditor := TComboBox.Create(nil);
FEditor.Parent := FComponent.Parent;
FEditor.Name := 'PluginIndexEditor';
FEditor.OnChange := PluginIndexChanged;
end;
destructor TPluginEditor.Destroy;
begin
FEditor.Free;
inherited;
end;
function TPluginEditor.GetProperties(Props: TStrings): Boolean;
begin
Props.AddObject('Component', FComponent, cmOwned);
Result := True;
end;
function TPluginEditor.Execute: Boolean;
begin
Result := False;
if Assigned(FComponent) then
begin
FComponent.PluginIndex := FEditor.ItemIndex;
Result := True;
end;
end;
procedure PluginIndexChanged(Sender: TObject);
begin
if Assigned(Sender) and Assigned(TComponent(Sender).Owner) then
TPluginEditor(Sender).Execute;
end;
end.
В этом примере создается пользовательский компонент TPluginEditor, который имеет свойство Component, ссылающееся на пользовательский компонент, для которого создается издатель свойств, и свойство Editor, ссылающееся на TComboBox, который будет использоваться для отображения списка доступных "плагинов". В методе GetProperties добавляется свойство Component в список свойств издателя, а в методе Execute устанавливается значение свойства PluginIndex пользовательского компонента на основе выбранного элемента в TComboBox.
Чтобы использовать этот издатель свойств, добавьте его в свойство CustomProperties пользовательского компонента:
unit MyCustomComponent;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, PluginEditor;
type
TMyCustomComponent = class(TComponent)
private
FPluginIndex: Integer;
procedure SetPluginIndex(Value: Integer);
public
property PluginIndex: Integer read FPluginIndex write SetPluginIndex;
property CustomProperties: TStrings read FCustomProperties write FCustomProperties;
end;
implementation
uses
System.SysUtils;
procedure TMyCustomComponent.SetPluginIndex(Value: Integer);
begin
if Value >= 0 then
FPluginIndex := Value;
end;
end.
В этом примере добавляется свойство CustomProperties, которое ссылается на список свойств издателя свойств. В методе GetProperties издателя свойств добавляется свойство Component, ссылающееся на пользовательский компонент, для которого создается издатель свойств.
При использовании этого издателя свойств пользователь может выбрать один из доступных "плагинов" в редакторе свойств пользовательского компонента, и значение свойства PluginIndex будет автоматически установлено на основе выбранного "плагина".
Альтернативный ответ
Другой подход к решению этой проблемы - использование механизма обнаружения единиц в проекте на основе имени файла. При использовании этого подхода вы можете проанализировать список единиц в проекте и проверить, присутствуют ли в нем единицы, соответствующие вашим "плагинам". Если они присутствуют, вы можете зарегистрировать их в глобальном списке и использовать их в пользовательском компоненте.
Вот пример кода, который демонстрирует, как проанализировать список единиц в проекте на основе имени файла в Object Pascal (Delphi):
unit PluginDetector;
interface
uses
System.SysUtils, System.Classes, Vcl.Forms;
type
TPluginDetector = class
private
FProject: TProject;
FPluginUnits: TStringList;
public
constructor Create(Project: TProject);
function DetectPlugins: TStringList;
end;
implementation
constructor TPluginDetector.Create(Project: TProject);
begin
inherited Create;
FProject := Project;
FPluginUnits := TStringList.Create;
FPluginUnits.CommaText := 'Unit1,Unit2,Unit3'; // список единиц, соответствующих вашим "плагинам"
end;
function TPluginDetector.DetectPlugins: TStringList;
var
I: Integer;
Unit: TUnit;
begin
Result := TStringList.Create;
for I := 0 to FProject.Uses.Count - 1 do
begin
Unit := FProject.Uses[I];
if FPluginUnits.ContainsText(Unit.UnitName) then
Result.Add(Unit.UnitName);
end;
end;
end.
В этом примере создается пользовательский компонент TPluginDetector, который имеет свойство Project, ссылающееся на проект, в котором нужно обнаружить единицы. В конструкторе устанавливается список единиц, соответствующих вашим "плагинам". В методе DetectPlugins проанализиров
Автоматическое обнаружение единиц в проекте для пакета пользовательского компонента - это проблема, связанная с обнаружением единиц в проекте, использующих пакет пользовательского компонента, и доступом к глобальному списку плагинов, зарегистрир
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.