Tôi có Biểu mẫu Delphi cung cấp chức năng đằng sau đối tượng giao diện mà các phần khác của mã cũng nhận được tham chiếu thông qua thuộc tính thuộc Biểu mẫu. Tôi không thể ủy quyền chức năng giao diện cho một đối tượng con vì quá nhiều chức năng đó được phục vụ bởi các điều khiển/thành phần trên biểu mẫu. Tôi không thể sử dụng TAggregatedObject hoặc TContainedObject để liên kết tuổi thọ của các đối tượng giao tiếp được truyền xung quanh Form vì lớp TForm không kế thừa từ TinterfacedObject và Delphi không hỗ trợ đa kế thừa vì vậy tôi không thể trộn trong TInterfacedObject vào chuỗi kế thừa . Tình huống này có thể dẫn đến vi phạm truy cập nếu một Biểu mẫu bị hủy trong khi một số mã khác giữ một trong các tham chiếu giao diện được Biểu mẫu truyền đi. Bất cứ ai có thể nghĩ ra một giải pháp tốt cho vấn đề này?Cách an toàn trong Delphi cho một Biểu mẫu để phân phối các đối tượng giao diện gắn liền với tuổi thọ của nó?
Trả lời
Bạn có thể ủy quyền giao diện cho đối tượng con, chỉ cần có đối tượng đó chứa con trỏ nội bộ vào biểu mẫu để có thể truy cập vào điều khiển của biểu mẫu khi cần, không khác gì bạn đang làm ngay bây giờ.
Bạn có thể sử dụng TAggregateObject
hoặc TContainedObject
cho các nhu cầu của mình. Họ không yêu cầu Biểu mẫu xuất phát từ TInterfacedObject
. Tất cả những gì họ yêu cầu là con trỏ giao diện IInterface
và TComponent
có nguồn gốc từ IInterface
(và ghi đè _AddRef()
và _Release()
để tắt tính tham chiếu), vì vậy bạn có thể vượt qua Biểu mẫu (là con số TComponent
) làm con trỏ yêu cầu IInterface
.
Điều đó để lại vấn đề duy nhất còn lại - Biểu mẫu đóng trong khi tham chiếu giao diện hoạt động đang được giữ bởi mã khác. Giải pháp đơn giản nhất là hoặc 1) viết lại mã đó để không giữ các tham chiếu đó trong khi Biểu mẫu đang đóng hoặc 2) không cho phép Biểu mẫu đóng cho đến khi các tham chiếu đó được giải phóng.
Lưu ý: Điều này sẽ chỉ hoạt động nếu người tiêu dùng của bạn cũng xuất phát từ TComponent.
Để tránh các tài liệu tham khảo chết bạn có thể truy vấn các IInterfaceComponentReference
(có sẵn trên tất cả các TComponent) từ mẫu của bạn, hãy gọi GetComponent
trên giao diện đó và gắn mình vào FreeNotification
của trở Component/Form.
gì xảy ra bây giờ là: Khi Form bị phá hủy nó sẽ thông báo cho tất cả "listners" rằng đi của nó để tiêu diệt chính nó bằng cách gọi phương thức Notification
trên người tiêu dùng với chính nó (theo mẫu) như AComponent
và opRemove
như hoạt động. Vì vậy, cho phép bạn nil tham chiếu giao diện của bạn. Nhưng lưu ý rằng tham chiếu đối tượng và tham chiếu giao diện không được bằng nhau. Cũng đảm bảo gọi số RemoveFreeNotification
khi bạn không cần thông báo nữa để tránh các cuộc gọi không cần thiết.
TSomeConsumer = class(TComponent)
private
FInterfaceToAService: ISomeInterface;
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
public
procedure SetService(const Value: ISomeInterface);
end;
procedure TSomeConsumer.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited;
if (Operation = opRemove) and (AComponent = TObject(FInterfaceToAService)) then
SetService(nil); // Takes care of niling the interface as well.
end;
procedure TSomeConsumer.SetService(const Value: ISomeInterface);
var
comRef: IInterfaceComponentReference;
begin
if Supports(FInterfaceToAService, IInterfaceComponentReference, comRef) then
comRef.GetComponent.RemoveFreeNotification(self);
FInterfaceToAService := Value;
if Supports(FInterfaceToAService, IInterfaceComponentReference, comRef) then
comRef.GetComponent.FreeNotification(self);
end;
Rất tuyệt! Tôi không biết về điều đó. Bạn có thể mở rộng một chút về tuyên bố của bạn - "Nhưng lưu ý rằng tham chiếu đối tượng và tham chiếu giao diện không được bằng nhau."? –
Vâng, một số lý do: a) bạn có thể thực hiện tùy chỉnh 'QueryInterface' có thể trả về một đối tượng giao tiếp mới trên mọi cuộc gọi. b) Thứ hai, bạn có thể ủy quyền Giao diện cho một thuộc tính (Win32), một lần nữa có thể tạo một đối tượng mới. c) Việc triển khai 'TObject.GetInterface' thêm một interfaceOffset vào địa chỉ.Giao diện mới được giới thiệu (Delphi 2010) cho đối tượng đúc về cơ bản được thực hiện bằng cách truy vấn một giao diện điểm đánh dấu trả về địa chỉ mục nhập của đối tượng. –
Điều gì sẽ xảy ra nếu đối tượng và tham chiếu giao diện là bình đẳng và sai lầm phổ biến nhất của một lập trình viên kết thúc việc tạo ra tình huống không mong muốn đó là gì? –
- 1. Mẫu bánh Scala cho các đối tượng có tuổi thọ khác nhau
- 2. Tuổi thọ của đối tượng trong Java vs .Net
- 3. python gắn liền với các mảng trong đối tượng json
- 4. Mục tiêu C "autorelease" trong C++ - cách tiêu chuẩn để kiểm soát tuổi thọ đối tượng?
- 5. Làm thế nào để quản lý tuổi thọ đối tượng khi làm việc với COM interop?
- 6. Tuổi thọ của các biến JavaScript
- 7. tuổi thọ của bảng temp
- 8. Tuổi thọ của biến tĩnh trong Android
- 9. Làm thế nào để đúc một giao diện cho một đối tượng ở Delphi
- 10. Trường tùy chỉnh cho Biểu mẫu đại diện cho một đối tượng
- 11. NSPopUpButton, Bindings và rút ngắn tuổi thọ
- 12. Phạm vi quản lý và tuổi thọ đối tượng Trong phạm vi STL Vectors
- 13. Phân phối an toàn các tệp từ Amazon S3
- 14. Mẫu C++ có các đối tượng giao diện
- 15. Làm thế nào để kéo dài tuổi thọ của biểu đồ trình tự trong Dia?
- 16. Xóa mẫu gắn liền với ember dữ liệu
- 17. C++ - biến tạm thời và tuổi thọ của chúng
- 18. Tuổi thọ của các vật thể tạm thời trong C11 và C99
- 19. OpenGL: yêu cầu tuổi thọ của mảng đỉnh
- 20. Triển khai các giao diện Java không an toàn
- 21. Có giao diện nào an toàn không?
- 22. ranh giới đầy đủ biểu hiện và tuổi thọ của temporaries
- 23. Các giao diện gắn thẻ trong Java
- 24. Tạo giao diện cho mẫu lớp trừu tượng trong C++
- 25. An ninh đối tượng trong phân tích cú pháp bằng cách sử dụng API JavaScript - Gắn kết người dùng với các đối tượng được lưu
- 26. Gắn cookie vào giao diện trong Symfony2
- 27. là nó chủ đề an toàn để gán một giá trị mới cho một đối tượng tĩnh trong C#
- 28. Làm thế nào để an toàn vượt qua một đối tượng bối cảnh trong một đại biểu UIAlertView?
- 29. Làm thế nào để phát triển các điều khiển giao diện phân phối cho iPhone?
- 30. Đảm bảo tuổi thọ tạm thời trong C++?
Lebeau, cảm ơn tôi sẽ sử dụng thông tin đó để sửa đổi mã của mình. –
Xin lỗi câu hỏi cuối, nhưng bạn có thể chỉ cho tôi một tham chiếu tốt giải thích khi nào sử dụng TContainedObject thay vì TAggregatedObject? Tôi đã nhìn chằm chằm vào Trợ giúp Delphi trong một thời gian và không thể thực sự xác định các trường hợp sử dụng khác biệt. –