PDA

View Full Version : سوال: تشخیص وجود یک متد در کلاس



یوسف زالی
چهارشنبه 30 شهریور 1390, 15:34 عصر
با سلام.
آیا راهی برای تشخیص وجود یک متد (با داشتن نام اون به صورت رشته) در یک کلاس (یا شی) وجود داره؟
منظور من رویداد هاش نیست.
فرض بفرمایید یک پروسیجر عمومی براش نوشته شده، می خوام وجودش رو در اشیا و کلاس ها چک کنم.
ممنون می شم اگر دوستان راهنمایی کنند.

BORHAN TEC
چهارشنبه 30 شهریور 1390, 16:51 عصر
یکی از راهها اینه که می تونید در پیاده سازی کلاسها از آن ایده بگیرید:
program Project1;

{$APPTYPE CONSOLE}

uses
SysUtils;

type
TBase = class
public
procedure myBaseMethod;
end;

TDrivedClass = class(TBase)
public
// Other Methods
end;

TMyClass = class
public
procedure anotherMethod;
end;

procedure TBase.myBaseMethod;
begin
// ...
end;

procedure TMyClass.anotherMethod;
begin
// ...
end;

var
obj: TBase;

begin

// an object
obj := TBase.Create;


Writeln(TMyClass.InheritsFrom(TBase));
Writeln(TDrivedClass.InheritsFrom(TObject));
Writeln(TMyClass.InheritsFrom(TObject));
Writeln(obj.InheritsFrom(TBase));
Writeln(TDrivedClass.InheritsFrom(obj.ClassType));

Readln;

end.
توجه داشته باشید که روش دیگری هم در کتاب Mastering Delphi 7 وجود داره که با اون میتونید لیست متدهای یک کلاس را استخراج کنید.

Felony
چهارشنبه 30 شهریور 1390, 17:56 عصر
برای بررسی وجود یک متد در یک شئ میشه همچین کدی نوشت :

procedure MethodExists(SourceObject: TObject; MethodName: string);
type
TExec = procedure of object;
var
Routine: TMethod;
Exec: TExec;
begin
Routine.Data := Pointer(SourceObject);
Routine.Code := SourceObject.MethodAddress(MethodName);
if Assigned(Routine.Code) then
begin
Exec := TExec(Routine);
Exec;
end
else
ShowMessageFmt('%s method not found', [MethodName]);
end;

برای استفاده (مثلا) یک Procedure با نام Test در بخش Public کلاس فرم برنامتون تعریف کنید :

type
TForm1 = class(TForm)
btnRunMethod: TButton;
procedure btnRunMethodClick(Sender: TObject);
procedure Test;
private
{ Private declarations }
public
{ Public declarations }
end;

و براش کد دلخواهتون رو بنویسید .

حالا برای تست :

MethodExists(Self, 'Test');
MethodExists(Self, 'Test1');

BORHAN TEC
چهارشنبه 30 شهریور 1390, 18:24 عصر
کد جالبی بود ولی مشکل اینجاست که این کد فقط می تواند متدهایی را شناسایی کند که در بخش Published تعریف شده باشد و قادر به شناسایی متدهای Public نیست. آیا برای رفع این مشکل هم راه حلی وجود دارد؟؟؟

vcldeveloper
چهارشنبه 30 شهریور 1390, 23:11 عصر
برای بررسی وجود یک متد در یک شئ میشه همچین کدی نوشت
فقط بررسی خروجی متد MethodAddress کفایت می کرد. مابقی اون کد برای فراخوانی متد مربوطه هست، که مربوط به سوال این تاپیک نمیشه.


ولی مشکل اینجاست که این کد فقط می تواند متدهایی را شناسایی کند که در بخش Published تعریف شده باشد و قادر به شناسایی متدهای Public نیست. آیا برای رفع این مشکل هم راه حلی وجود دارد؟؟؟
اگر از دلفی 2010 یا نسخه های جدیدتر دلفی استفاده می کنید، به طور پیش فرض می تونید با استفاده از RTTI اطلاعات مربوط به اعضاء public و published یک کلاس رو به دست بیارید. برای داده های Private یا Protected، باید از طریق Compiler Directives به کامپایلر دستور داده بشه که برای اون بخش از داده ها هم RTTI تولید کنه. کدی که می تونید استفاده کنید، به این صورت هست:


uses RTTI;

function MethodExitsts(Obj: TObject; const MethodName: string): Boolean;
var
Context : TRttiContext;
AType : TRttiType;
AMethod : TRttiMethod;
begin
Result := False;
Context := TRttiContext.Create;
try
AType := Context.GetType(Obj.ClassType);
if Assigned(AType) then
for AMethod in AType.GetMethods do
if SameText(AMethod.Name, MethodName) then
Exit(True);
finally
Context.Free;
end;
end;

یوسف زالی
پنج شنبه 31 شهریور 1390, 00:06 صبح
از تمام دوستان ممنونم ..
من از دلفی 7 استفاده می کنم.
آیا استفاده از RTTI باعث سرباره می شه؟
در کل چرا به صورت پیش فرض این قابلیت فعال نیست؟

vcldeveloper
پنج شنبه 31 شهریور 1390, 00:12 صبح
من از دلفی 7 استفاده می کنم.استفاده از کد بالا برای شما منتفی هست، چون دلفی 7 فقط برای داده های published داده های RTTI تولید میکنه.


آیا استفاده از RTTI باعث سرباره می شه؟طبیعی هست که استفاده از RTTI برای پیدا کردن یک داده خاص زمان بیشتری نسبت به حالتی که بدونید اون داده کجا هست، نیاز خواهد داشت.


در کل چرا به صورت پیش فرض این قابلیت فعال نیست؟ RTTI به طور پیش فرض برای داده های Public و Published در دلفی 2010 و نسخه های بعد از آن، و فقط برای داده های Published برای نسخه های قدیمی دلفی در دسترس هست. چه لزومی داره که یک کد بخواد به داده های خصوصی یک کلاس دسترسی پیدا کنه (البته بحث Serialization هست، که در اون حالت هم به نظر من لزومی نداره)، در صورتی که توسعه دهنده اون کلاس خاص مایل نباشه که اون داده ها در دسترس دیگران قرار بگیره؟ اگر توسعه دهنده اون کلاس مایل به انجام همچین کاری باشه، میتونه به کامپایلر اطلاع بده، تا RTTI برای داده های خصوصی کلاسش هم تولید بشه، در غیر اینصورت، کامپایلر کاری به کار داده های خصوصی اون کلاس نخواهد داشت.

یوسف زالی
پنج شنبه 31 شهریور 1390, 00:16 صبح
من نیاز پیدا کردم وجود یک متد public رو در کلاس تشخیص بدم.
آیا راهی در 7 نیست؟
ممنون از اینکه با دانشتون راهنمایی می فرمایید.

Felony
پنج شنبه 31 شهریور 1390, 02:37 صبح
فقط بررسی خروجی متد MethodAddress کفایت می کرد. مابقی اون کد برای فراخوانی متد مربوطه هست، که مربوط به سوال این تاپیک نمیشه.
بله ، گفتم تو همون کد نحوه اجرای متد با نامش رو هم بنویسم شاید به کارشون اومد ...

BORHAN TEC
جمعه 01 مهر 1390, 21:35 عصر
با توجه به پست 3:
در این پست نحوه فراخوانی یک متد ساده آورده شده است ولی در اینجا دو تا سوال برایم پیش آمده است:

1- چطور می توان متدی را فراخوانی کرد که یک یا چندین پارامتر دارد؟
2- چگونه باید به مقدار خروجی یک متد دسترسی داشت؟

vcldeveloper
یک شنبه 03 مهر 1390, 11:57 صبح
1- چطور می توان متدی را فراخوانی کرد که یک یا چندین پارامتر دارد؟
2- چگونه باید به مقدار خروجی یک متد دسترسی داشت؟
جواب هر دو تا میشه: RTTI.