2011-09-02 7 views
5

Tôi gặp lỗi thời gian chạy xảy ra trong rtl Truyền trực tuyến trong biểu mẫu, khiến EClassNotFound ngoại lệ được nâng lên, trong khi thực hiện TReader.ReadRootComponent. Thông báo lỗi cụ thể là "Lớp không tìm thấy TActionList".EClassNotFound tăng lên trong thời gian chạy thực sự có ý nghĩa gì khi lớp học được đề cập có thời gian biên dịch và liên kết và có mã rõ ràng?

là gì kỳ lạ là:

  1. hình thức chính của tôi sử dụng danh sách hành động.
  2. Để giải trí, tôi đã thêm ActnList.pas (từ thư mục nguồn VCL) vào dự án của mình, để cố gắng khắc phục nó.

Điều này xảy ra với tôi khi khởi tạo biểu mẫu mà tôi đã làm việc cho đến vài phút trước. Thay đổi mà tôi đã thực hiện là trong một số mã khung phụ: Tôi đã xóa tất cả mã phần triển khai của nó bằng một dấu ifdef, vì tôi đang nhạo một số khung hình, để kiểm tra đơn vị và nguyên mẫu.

Tôi đã thử thêm lớp danh sách hành động vào dự án và tôi đã thử và không có các tùy chọn trình biên dịch và liên kết khác nhau, tuy nhiên, tôi vẫn nhận được ngoại lệ này. Rõ ràng là điều gì đó kỳ lạ đang lên. Phải có một cách khác lạ để giải quyết vấn đề này.

Thực tế, có vẻ như có điều gì đó thực sự kỳ lạ đang xảy ra. Khi lỗi này được nâng lên, tôi nhận được cuộc gọi stack sau:

rtl.Classes.ClassNotFound('TActionList') 
rtl.Classes.TReader.FindComponentClass(???) 
rtl.Classes.FindExistingComponent 
rtl.Classes.TReader.ReadComponent(nil)  /// NIL!? WHAT!!!!! 
rtl.Classes.TReader.ReadDataInner(???) 
rtl.Classes.TReader.ReadData(???) 
rtl.Classes.TComponent.ReadState(???) 
vcl.Controls.TControl.ReadState(???) 
vcl.Controls.TWinControl.ReadState($60B9CF0) 
vcl.Forms.TCustomForm.ReadState(???) 
rtl.Classes.TReader.ReadRootComponent($606EB90) 
rtl.Classes.TStream.ReadComponent($606EB90) 
rtl.Classes.InternalReadComponentRes(???,???,$606EB90) 
rtl.Classes.InitComponent(TComplexFormContainingFrames) 

Có vẻ như con số không là cố ý, trong TReader.ReadDataInner (Instance: TComponent):

 while not EndOfList do ReadComponent(nil); 

Cập nhật: Tôi tin câu trả lời cho câu hỏi này là hiểu "ngữ cảnh tuần tự hóa" như Mason đã đề cập. Và, đó là thời gian để thừa nhận sự ngu ngốc của riêng tôi: Tôi loại bỏ cha mẹ của khung hình từ dự án, không nhận ra nó là cha mẹ của khung. Tôi đã làm việc xung quanh nó bị thiếu bằng cách đưa ra tuyên bố loại cho TMyFrameParentTMyFrameParent = class(TFrame) và điều này sẽ dẫn đến điều kiện được đề cập. Tôi để lại câu hỏi ở đây bởi vì tôi nghĩ rằng nó có thể thực sự tiện dụng trong tương lai để lưu ý khi ngoại lệ này xảy ra trong trường hợp phức tạp, và làm thế nào để sửa chữa nó. Đặc biệt, Mason có một chút thông tin thú vị về "bối cảnh tuần tự hóa" và cách chúng áp dụng cho việc tìm kiếm tên lớp.

+1

Nil chỉ báo hiệu cho ReadComponent để khởi tạo một phiên bản mới thay vì đọc vào một phiên bản hiện có. –

Trả lời

6

Điều đó có nghĩa là lớp học không được tìm thấy trong ngữ cảnh deserialization hiện tại. Không phải tất cả các lớp hiện có đều được đăng ký cho tất cả các lần tải. Mỗi lớp biểu mẫu có RTTI chứa tham chiếu đến các thành phần mà nó sử dụng. Để có được điều này để làm việc, hãy chắc chắn rằng hình thức của bạn (hoặc khung hình, nếu điều này là một khung) tuyên bố ít nhất một TActionList trước thẻ tin:

TMyForm = class(TForm) 
    ActionList: TActionList; 
    OtherComponent: TSomeComponent; 
private 
    //whatever 
public 
    //whatever 
end; 
2

Sử dụng Classes.RegisterClass để đăng ký lớp bạn muốn sử dụng với hệ thống phát trực tuyến. Trích dẫn từ tài liệu

Lớp biểu mẫu và lớp thành phần được tham chiếu trong tuyên bố biểu mẫu (biến mẫu) được đăng ký tự động. Bất kỳ lớp nào khác được ứng dụng sử dụng phải được đăng ký rõ ràng bằng cách gọi RegisterClass nếu các cá thể được lưu. Khi các lớp được đăng ký, chúng có thể được tải hoặc lưu bởi hệ thống phát trực tuyến thành phần.

+0

Vì vậy, trong trường hợp khung được kế thừa từ khung khác, có lẽ điều này giải thích tại sao Classes.RegisterClass không bao giờ được gọi, bởi vì .dfm của khung chỉ chứa mục nhập "kế thừa x" chứ không phải mục nhập "đối tượng x". –

+0

Có một cái gì đó đáng sợ ... nếu dự án không chứa khung chính, thì hệ thống phát trực tuyến sẽ tìm kiếm lớp TActionList như thế nào? Bởi vì dfm cho khung con cháu trống (tức là không chứa ActionList), phải không? – ain

1

Dường như điều này xảy ra khi bạn sao chép một khung từ một dự án để dự án khác, và khung được thừa kế từ một cái gì đó, và bạn giả thừa kế, nhưng rời khỏi giới thiệu mục "thừa hưởng" trong dfm khung, các mục như thế này:

inherited ActionList: TActionList 
    Left = 520 
    Top = 576 
end 

này trong kết quả lần lượt trong "bối cảnh deserialization hiện tại" mà Mason nói về, không chứa các lớp. Một sửa chữa là thay đổi Thừa kế với đối tượng trong tất cả các trường hợp trên.