unit Myc.Utils;

interface

type
    TManaged<T: class> = record
    private
        type
            TObj = class(TInterfacedObject)
                FValue: T;
                constructor Create(AValue: T);
                destructor Destroy; override;
            end;
        var
            FIntf: IInterface;
    public
        class operator Implicit(A: T): TManaged<T>; overload;
        class operator Implicit(const Upvalue: TManaged<T>): T; overload;
    end;

    TGenericContainedObject<T: TInterfacedObject> = class(TObject, IInterface)
    private
        FController: TInterfacedObject;
    protected
        function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
        function _AddRef: Integer; stdcall;
        function _Release: Integer; stdcall;
        property Controller: TInterfacedObject read FController;
    public
        constructor Create(AController: TInterfacedObject);
    end;

implementation

constructor TManaged<T>.TObj.Create(AValue: T);
begin
    inherited Create;
    FValue := AValue;
end;

destructor TManaged<T>.TObj.Destroy;
begin
    FValue.Free;
    inherited;
end;

class operator TManaged<T>.Implicit(A: T): TManaged<T>;
begin
    Result.FIntf := TObj.Create(A);
end;

class operator TManaged<T>.Implicit(const Upvalue: TManaged<T>): T;
begin
    Result := (Upvalue.FIntf as TObj).FValue;
end;

constructor TGenericContainedObject<T>.Create(AController: TInterfacedObject);
begin
    inherited Create;
    FController := AController;
end;

{ TGenericContainedObject }

function TGenericContainedObject<T>.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
    if GetInterface(IID, Obj) then
        Result := S_OK
    else
        Result := E_NOINTERFACE;
end;

function TGenericContainedObject<T>._AddRef: Integer;
begin
    Result := IInterface(FController)._AddRef;
end;

function TGenericContainedObject<T>._Release: Integer;
begin
    Result := IInterface(FController)._Release;
end;

end.
