2010-06-18 39 views
14

Như chúng ta đều biết, khi chúng ta gọi một constructor của một lớp như thế này:Làm thế nào để tạo một thể hiện đối tượng với RTTI trong Delphi 2010?

instance := TSomeClass.Create; 

Trình biên dịch Delphi thực sự làm những điều sau đây:

  1. Gọi newInstance tĩnh phương pháp để cấp phát bộ nhớ và khởi tạo bố cục bộ nhớ.
  2. Gọi phương thức khởi tạo để thực hiện khởi tạo của lớp
  3. Gọi phương pháp AfterConstruction

Rất đơn giản và dễ hiểu. nhưng tôi không chắc chắn cách trình biên dịch xử lý các ngoại lệ trong bước thứ hai và thứ ba.

Dường như không có cách nào rõ ràng để tạo một cá thể bằng cách sử dụng phương thức hàm tạo RTTI trong D2010. vì vậy tôi đã viết một hàm đơn giản trong khung công tác Spring cho Delphi để tạo lại quá trình tạo ra.

class function TActivator.CreateInstance(instanceType: TRttiInstanceType; 
    constructorMethod: TRttiMethod; const arguments: array of TValue): TObject; 
var 
    classType: TClass; 
begin 
    TArgument.CheckNotNull(instanceType, 'instanceType'); 
    TArgument.CheckNotNull(constructorMethod, 'constructorMethod'); 
    classType := instanceType.MetaclassType; 
    Result := classType.NewInstance; 
    try 
    constructorMethod.Invoke(Result, arguments); 
    except 
    on Exception do 
    begin 
     if Result is TInterfacedObject then 
     begin 
     Dec(TInterfacedObjectHack(Result).FRefCount); 
     end; 
     Result.Free; 
     raise; 
    end; 
    end; 
    try 
    Result.AfterConstruction; 
    except 
    on Exception do 
    begin 
     Result.Free; 
     raise; 
    end; 
    end; 
end; 

Tôi cảm thấy nó có thể không đúng 100%. vì vậy xin vui lòng chỉ cho tôi cách. Cảm ơn!

Trả lời

18

Gọi hàm tạo và chuyển lớp như đối số Self (trái ngược với một thể hiện) sẽ xây dựng lớp một cách chính xác. Quá trình xây dựng bao gồm NewInstance, AfterConstruction v.v. mà bạn đang thực hiện thủ công ở đây: không cần thiết.

phải này là đủ:

Result := constructorMethod.Invoke(instanceType.MetaclassType, arguments); 

Một kỳ quặc của Delphi là cách nó cho phép nhà thầu được gọi vào trường cũng như các lớp học. Tính năng này được sử dụng như một loại "vị trí mới" (trong thuật ngữ C++) để xây dựng biểu mẫu, do đó biến dạng toàn cục (ví dụ: Form1 theo mặc định cho biểu mẫu đầu tiên) được chỉ định tại thời điểm hàm tạo OnCreate được gọi. Do đó, mã của bạn không làm tăng ngoại lệ. Nhưng nó là bình thường hơn để vượt qua lớp chứ không phải là ví dụ như đối số Self.

+0

Cảm ơn bạn rất nhiều! Cuối cùng tôi đã có lý do tại sao có một quá tải của Invoke với một tham số lớp. –

+0

@Paul: Quá tải đó cũng có thể được sử dụng để gọi các phương thức ** lớp **. –

+0

Vâng. Nhưng tôi đã nhầm lẫn với tên của tham số. (Ví dụ: TClass ...) –

Các vấn đề liên quan