문제

제공된 외부 개체를 사용하여 TWebBrowser(TEmbeddedWB 사용)를 통해 복잡한 값을 수신하고 잠재적으로 전송하려고 합니다.예를 들어;자바스크립트에서는 배열을 매개변수로 사용하여 노출된 메소드를 사용하려고 합니다.

var test = [123, 'abc'];
external.someFunction(test);

//Or something more complex
var complexObject = {
  someMethod : function(){ return 1; },
  someProperty : 123,
  someArray : ['xyz', 3.14]
}
external.someFunction(complexObject);

이 두 예제의 VarType을 확인하면 IDispatch라는 것을 알 수 있습니다.

function TSomeClass.someFunction(var Param : OleVariant) : OleVariant;
var
  vType : Integer;
begin
  vType := (VarType(Param) and VarTypeMask); //Says 9 (varDispatch)
  Result := true;
end;

저는 COM에 대해 잘 알지 못해서 어떻게 작업해야 할지 잘 모르겠습니다.

어떤 도움이라도 주시면 감사하겠습니다.

도움이 되었습니까?

해결책

JScript 개체를 다른 OleVariant COM 개체와 마찬가지로 처리할 수 있습니다.배열 측면에서 몇 가지 문제가 있습니다(그리고 거의 모든 JScript 개체는 본질적으로 희소 배열입니다).

JScript 개체를 OleVariant로 가져온 후 일반 코드처럼 간단히 호출할 수 있습니다(물론 컴파일 시간 확인 없이).

다음은 배열을 처리하기 위한 몇 가지 코드입니다.

type
  TJScriptArray = class
  private
    FArray:   IDispatchEx;
    FCount:   Integer;
    function  GetProperty( const AName: String ): OleVariant;
    function  GetItem(Index: Integer): OleVariant;
  public
    constructor Create( AObj: OleVariant );
    destructor  Destroy; override;
  public
    property  Count: Integer read FCount;
    property  Item[Index: Integer]: OleVariant read GetItem; default;
  end;

function  VarToDispatchEx( const AObject: OleVariant ): IDispatchEx;
begin
  Result := nil;
  if VarType( AObject ) <> varDispatch then
    Exit;
  Supports( IDispatch(AObject), IDispatchEx, Result );
end;

function  IsJScriptArray( const AObject: OleVariant ): Boolean;
var
  temp: IDispatchEx;
begin
  temp := VarToDispatchEx( AObject );
  Result := temp <> nil;
end;


constructor TJScriptArray.Create(AObj: OleVariant);
begin
  inherited Create;
  FArray := VarToDispatchEx( AObj );
  if FArray = nil then
    raise Exception.Create( 'TJscriptArray called with invalid parameters.' );
  FCount := GetProperty( 'length' );
end;

destructor TJScriptArray.Destroy;
begin
  inherited Destroy;
end;

function TJScriptArray.GetItem(Index: Integer): OleVariant;
begin
  if Index > FCount then
    raise Exception.Create( 'Index out of bounds.' );
  Result := GetProperty( IntToStr( Index ) );
end;

function TJScriptArray.GetProperty(const AName: String): OleVariant;
var
  sz: WideString;
  id: Integer;
  res: Variant;
  ei: TExcepInfo;
  params: TDispParams;
  hr: HResult;
begin
  {
    ACTION: return the specified property from the jscript array
    NOTE:   since a jscript array is a sparse array there may be
            gaps. In that case a null variant is returned. This is
            signalled by the name (id) not existing.
  }
  sz := AName;
  hr := FArray.GetDispID( PWideChar(sz), 0, id );
  if hr = disp_e_UnknownName then begin
    Result := Null;
    Exit;
    end
  else
    OleCheck( hr );

  VarClear( res );
  FillChar( ei, sizeof(ei), 0 );
  FillChar( params, sizeof(params), 0 );
  OleCheck( FArray.InvokeEx( id, 0, dispatch_PropertyGet, @params, @res, @ei, nil ) );
  Result := res;
end;

다른 팁

나는 당신이 시도하고있는 일을 직접하지 않았지만.

변형을 사용하면 실제로 메소드와 속성에 동적으로 액세스 할 수 있습니다.

기본적으로 나는 당신이 모든 것을 직접 액세스 할 수 있어야한다고 생각합니다.

Param.Someproperty
Param.SomeArray[1]
Param.SomeMethod();

상황이 잘못되면 컴파일 시간 오류가 발생하지 않으므로 조심하십시오.

예를 들어 다음 코드는 컴파일되지만 해당 변수에 동적으로 할당되지 않으므로 유효하지 않은 변형 작업의 런타임 오류를 제공합니다.

var
 vo : OleVariant;
 v  : Variant;
begin
  v.DoThis;
  vo.DoThat;
end;

JavaScript 객체 표기법 (JSON)을 사용하여 복잡한 데이터 직렬화를 고려 했습니까? 이를 통해 임의의 JavaScript 객체를 직렬화하고 간단한 문자열로 전달하여 델파이 코드로 재구성 할 수 있습니다.

Delphi 2009는 새로운 DataSNAP의 일환으로 JSON을 지원합니다 (독립형 사용이 얼마나 쉬운 지 확실하지 않음). 유용 할 수있는 많은 Delphi JSON 구현도 있습니다.

점검 LKJSON 그리고 JSON- 슈퍼오버

저는 JSON의 전문가는 아니지만, 언어 교차 데이터 교환을위한 상대적으로 간단하고 효율적인 솔루션 인 것 같습니다.

데이비드

JavaScript의 객체 연관 어레이입니다, 속성 이름은 키입니다 : obj.prop 동일합니다 obj['prop'].

일반 어레이는 단순히 인덱스를 속성으로 저장하는 객체이므로 희소 배열처럼 행동합니다.

Delphi의 Olevariants는 속성에 직접 액세스 할 수 있지만 이름이 유효한 경우에만 델파이 식별자, 숫자 인덱스를 속성 이름으로 사용하는 것을 좋아하지 않습니다 (예 : obj.0 컴파일하지 않습니다).

잘못된 식별자 이름을 가진 속성을 읽을 수 있습니다 DISPATCH_PROPERTYGET 에서와 같이 라이언의 반응.

그러나 델파이에는 적절한 루틴이 포함되어 있습니다 ComObj직접 수행 할 장치 :

uses ComObj;

...

function TSomeClass.someFunction(var Param : OleVariant) : OleVariant;
begin
  ShowMessage(Param.someProperty); // 123
  ShowMessage(GetDispatchPropValue(Param, 'someProperty')); // 123

  ShowMessage(Param.someArray.length); // 2
  ShowMessage(GetDispatchPropValue(Param.someArray, '0')); // xyz

  Result := true;
end;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top