2015-03-18 34 views
8

Tôi đã viết một hàm chấp nhận loại lớp (T) và loại giao diện (I) và trả về một giao diện (I) cho đối tượng (T). Đây là mã.Sử dụng Generics để tạo một đối tượng giao tiếp

interface 

function CreateObjectInterface<T: Class, constructor; I: IInterface>(
    out AObject: TObject): I; 

...

implementation 

function TORM.CreateObjectInterface<T, I>(out AObject: TObject): I; 
begin 
    AObject := T.Create; 

    if not Supports(AObject, GetTypeData(TypeInfo(I))^.Guid, Result) then 
    begin 
    AObject.Free; 
    AObject := nil; 

    raise EORMUnsupportedInterface.CreateFmt(
     'Object class "%s" does not support interface "%s"', 
     [AObject.ClassName, GUIDToString(GetTypeData(TypeInfo(I))^.GUID)] 
    ); 
    end; 
end; 

Chức năng hoạt động như dự kiến ​​không có rò rỉ bộ nhớ hoặc virus chẳng ai ưa khác.

Có cách nào khác để đạt được kết quả tương tự không?

+5

Tôi không chắc rằng điều này câu hỏi là thích hợp ở đây. Có lẽ xem xét mã sẽ là một trang web tốt hơn. Câu hỏi cuối cùng của bạn chắc chắn là dựa trên ý kiến. Hai câu hỏi đầu tiên. 1. Có, điều này là OK. 2. Không, không có vấn đề gì. –

+0

Đặt lại câu hỏi cuối cùng thành "có cách nào khác để đạt được kết quả tương tự không?" –

+0

@LURD - Tôi đã lặp lại câu hỏi – norgepaul

Trả lời

14

Có lỗi trong mã này. Hỗ trợ sẽ phá hủy cá thể đối tượng của bạn nếu nó hỗ trợ IUnknown nhưng không phải là giao diện bạn đang yêu cầu.

Simple trình diễn:

type 
    IFoo = interface 
    ['{32D3BE83-61A0-4227-BA48-2376C29F5F54}'] 
    end; 

var 
    o: TObject; 
    i: IFoo; 
begin 
    i := TORM.CreateObjectInterface<TInterfacedObject, IFoo>(o); // <- boom, invalid pointer 
end. 

tốt nhất để đưa càng thêm IInterface hoặc IUnknown chế để T.

Hoặc đảm bảo rằng bạn không hủy một phiên bản đã bị hủy.

Trừ khi bạn muốn hỗ trợ năng động QueryInterface triển khai (trong đó lớp không thực hiện giao diện nhưng QueryInterface trở về như cũ) Tôi sẽ đi với một cuộc gọi Supports trên lớp:

function TORM.CreateObjectInterface<T, I>(out AObject: TObject): I; 
begin 
    if not Supports(TClass(T), GetTypeData(TypeInfo(I))^.Guid) then 
    raise EORMUnsupportedInterface.CreateFmt(
     'Object class "%s" does not support interface "%s"', 
     [AObject.ClassName, GUIDToString(GetTypeData(TypeInfo(I))^.GUID)] 
    ); 

    AObject := T.Create; 
    Supports(AObject, GetTypeData(TypeInfo(I))^.Guid, Result); 
end; 
+0

Tốt bắt Stefan. – norgepaul

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