2013-06-21 15 views
6

Ben örnek bir sınıf yardımcıDelphi Sınıf Yardımcısı RTTI GetMethod

TSampleClassHelper = class helper for TSampleClass 
public 
    procedure SomeHelper; 
end; 

aşağıdaki yok değil düşünelim.

Fakat bunun yerine yardımcı yöntemi çağırmak için RTTI'yi nasıl kullanabilirim? Aşağıdaki işe yaramıyor gibi görünüyor, GetMethod nil döndürür.

var 
    obj :TSampleClass; 
    ctx :TRTTIContext; 
    rtype :TRTTIType; 
    rmethod :TRTTIMethod; 
begin 
    obj:=TSampleClass.Create; 
    rtype:=ctx.GetType(obj.ClassType); 
    rmethod:=rtype.GetMethod('SomeHelper'); // rmethod is nil ! 
end; 

RTTI, sınıf yardımcılarında tanımlanan yöntemler için işe yaramıyor mu? Bunun etrafında zaten var mı?

Teşekkürler.

+0

Anlıyorum, ama benim gerçek hayat kodunda herhangi keyfi nesneye karşı 'birYöntem' için test ediyorum. Nesnenin bir yardımcı ile tanımlanmış metodu olup olmadığını bilmiyorum.Yani sanırım bir sınıf yardımcısı tarafından tanımlanan 'SomeMethod' için çalışmayacak. Oh iyi. –

cevap

8

Kodunuzun nil yöntemini döndürmesinin nedeni, nesnenin türünün SomeHelper adlı bir yöntem içermemesidir. Bu yöntemi içeren tür yardımcısı türüdür.

Yani, olmayan bir nil yöntemini dönecektir hangi bu yazabiliriz: Elbette

obj:=TSampleClass.Create; 
rtype:=ctx.GetType(TypeInfo(TSampleClassHelper)); 
rmethod:=rtype.GetMethod('SomeHelper'); 

, hemen ilk sorunu, bir derleme zamanı belirtilen türün, yani kullanmak, TSampleClassHelper görmelisiniz. Çalışmanın türüne göre çalışma zamanında TSampleClassHelper'u bulmak için RTTI kullanabilir miyiz? Hayır, aşağıda açıklayacağım gibi yapamayız.

Bunu bir kenara koysak bile, görebildiğim kadarıyla, RTTI kullanarak yöntemi çağırmanın bir yolu yoktur. rmethod.Invoke(obj, [])'u çağırırsanız, TRttiInstanceMethodEx.DispatchInvoke'daki kod, yardımcı yöntemi çağırmaya yönelik bir girişimi engeller. Örneğin türünün yöntemin sınıfı ile uyumlu olmadığını bildirdiği için onu engeller. ilgili kodudur:

if (cls <> nil) and not cls.InheritsFrom(TRttiInstanceType(Parent).MetaclassType) then 
    raise EInvalidCast.CreateRes(@SInvalidCast); 

Eh, rmethod.CodeAddress ile yardımcı yönteminin kod adresini elde edebilirsiniz ama bu yöntemi çağırmak için başka bir yol bulmak gerekir. Uygun imza ile bir yönteme dökmek ve onu çağırmak için yeterince kolaydır. Ama neden rmethod.CodeAddress ile her durumda rahatsız? Neden TSomeHelperClass.SomeMethod'u kullanmıyorsunuz ve RTTI'yi döngüden kesiyorsunuz?

Tartışma

Yardımcısı çözünürlük derleme noktada etkin yardımcı dayalı statik gerçekleştirilir. RTTI kullanarak bir yardımcı metodu çağırmaya çalıştığınızda, aktif yardımcısı yoktur. Tamamladıktan sonra uzun zaman oldu. Yani hangi yardımcı sınıfın kullanılacağına karar vermelisiniz. Bu noktada, RTTI'ye ihtiyacınız yok.

Buradaki temel sorun, sınıf yardımcı yöntemi çözümlemesinin temel olarak derleyicinin bağlamı kullanılarak gerçekleştirilen statik bir süreç olmasıdır. Çalışma zamanında derleyici bağlamı olmadığından, sınıf yardımcı yöntemi çözümlemesi RTTI kullanılarak gerçekleştirilemez. Bu işe daha iyi kavramak için

burada Allen Bauer'in cevabın bir okuma vardır: Find all Class Helpers in Delphi at runtime using RTTI?

+0

Bir sınıf için çok sayıda yardımcı var. Bazı sınıfların, bir yardımcı tarafından tanımlanan, bazılarının yapmadığı gerekli yöntemi vardır. Örneğin, TStrings için yöntemi bir yardımcı yardımıyla ekledim, ancak TMyClass için doğrudan sınıfta tanımlandı. –

+0

@AJ. Asıl konu, derleyici tarafından derleme bağlamına dayalı olarak yardımcı yöntem çözümünün statik olarak gerçekleştirilmesidir. Bu kavram RTTI'ye tamamen ortogonaldir. –