외부 인터페이스를 통해 복잡한 자바스크립트 값 수신
-
06-09-2019 - |
문제
제공된 외부 개체를 사용하여 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;