تلقي قيم جافا سكريبت معقدة من خلال واجهة خارجية
-
06-09-2019 - |
سؤال
أحاول تلقي وقيم معقدة محتملة من خلال TwebBrowser (باستخدام tembeddedwb) مع الكائن الخارجي المقدم. علي سبيل المثال؛ في JavaScript، سأحاول استخدام الأسلوب المكشوف مع صفيف كمعلمة:
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;
أنا لست على دراية كوم ولست متأكدا من كيفية العمل مع هذا.
سيكون موضع تقدير أي مساعدة.
المحلول
يمكنك التعامل مع كائن JScript تماما مثل أي كائن OleVariant COM آخر. هناك عدد قليل من gotchas من حيث المصفوفات (وعن أي كائن 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 على دعم JSON كجزء من DataSnap الجديد (غير متأكد من مدى سهولة استخدام المستقل). هناك أيضا عدد من تطبيقات دلفي JSON هناك قد تكون مفيدة:
الدفع lkjson. و json - superobject.
أنا لا خبير في JSON، لكن يبدو أنه حل بسيط وفعال نسبي لتبادل البيانات عبر اللغة.
ديفيد
كائنات في جافا سكريبت هي صفائف النظامية, مع أسماء الممتلكات كونها مفاتيح: obj.prop
أي ما يعادل obj['prop']
.
الصفائف العادية هي ببساطة كائنات تخزين الفهارس كخصائص، لذلك يتصرفون مثل صفيفات متفرقة.
السماح olevariants delphi بالوصول المباشر إلى العقارات، ولكن فقط عندما تكون أسمائهم صالحة معرفات دلفي, ، لذلك لا يحب استخدام مؤشر رقمي كاسم خاصية (أي 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;