gpt4 book ai didi

reflection - 在 C# 4 中使用动态类型访问 javascript 对象的属性

转载 作者:行者123 更新时间:2023-12-03 20:40:07 26 4
gpt4 key购买 nike

我在 c# 中将 com 对象定义为动态类型,我可以很容易地调用方法。
但是,当我尝试访问同一对象上的属性时,我收到了无效的强制转换异常。

有问题的对象是一个数组,从 JavaScript 传递给托管代码,我希望以 int 形式获取它的 length 属性。

我知道我遗漏了一些奇怪的东西,因为我没有收到“不包含定义”的异常,而且我可以使用反射/InvokeMember 轻松访问该属性。

为什么我不能将动态类型的长度属性转换为 int?

例如

这失败

   dynamic com = comObject;
int i = com.length; // RTBE here.

此作品
   Type type = comObject.GetType();
int i = (int)type.InvokeMember("length", BindingFlags.GetProperty, null, comObject, null);

* 更新 *

经过大量测试后,我将这种奇怪现象缩小到多维数组的情况。
有问题的 com 对象是从 html 文档传递到托管代码的参数。出于所有意图和目的,对象有时在 JavaScript 中看起来像这样。
var x = ["a1", "a2", "a3"];

当这样的数组出现在托管代码中时,我可以使用类型 dynamic 获得长度 AOK。 (即这里第一个失败的例子实际上有效)。但是,如果它是多维数组,例如 JavaScript 中的以下结构。
var y = [["b1", "b2", "b3"], "a2", "a3"];

然后在尝试动态访问其长度属性时出现错误。请注意,在这种情况下,我仍然可以通过反射访问长度。在我看来,由于某种原因,当多维数组用作动态类型时,长度属性没有得到正确映射......

在我的情况下,我为解决(!?)所做的事情是在传递它之前向数组添加一个“length_”属性。
var y = [["b1", "b2", "b3"], "a2", "a3"];
y.length_ = y.length;

现在在托管代码中,我可以按预期访问此属性而不会出错。远非理想,但似乎有效......
   dynamic com = comObject;
int i = com.length_; // 3!

进一步更新

好的,所以看起来对象索引和长度属性一样也会丢失到动态类型中。再次可以通过反射访问它...

失败
   dynamic com = comObject; // js array i.e. var x = [1, 2];
int i = com[0]; // MissingMemberException - Error while invoking [PROPERTYGET, DISPID(0)].
int i = com["0"]; // MissingMemberException - Error while invoking [PROPERTYGET, DISPID(0)].

作品
   Type type = comObject.GetType();
int i = (int)type.InvokeMember("0", BindingFlags.GetProperty, null, comObject, null); // 1

最佳答案

简单来说,您无法通过类型 dynamic 访问 c# 中多维数组的 length 属性,除非您似乎首先在 JavaScript 中使用了 length 属性...

下面的简单测试非常清楚地显示了这一点。我希望这能让其他人免于我在过去一天左右的时间里头疼的问题。

[ComVisibleAttribute(true)]
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
webBrowser1.ObjectForScripting = this;

StringBuilder html = new StringBuilder();
html.Append("<script>");
html.Append("var arr1 = [1, 2, 3, 4];");
html.Append("var arr2 = [arr1, 2, 3, 4];");
html.Append("var fn1 = function() { return arr1; };");
html.Append("var fn2 = function() { return arr2; };");
html.Append("var fn3 = function() { alert(arr2.length); }");
html.Append("</script>");
webBrowser1.DocumentText = html.ToString();

webBrowser1.DocumentCompleted += (o, e) =>
{
dynamic arr1 = webBrowser1.Document.InvokeScript("fn1");
int i = arr1.length;
MessageBox.Show(i.ToString()); //4

// If I call fn3 here then the arr2.length *is* available as int i2 below!
////webBrowser1.Document.InvokeScript("fn3"); // 4

dynamic arr2 = webBrowser1.Document.InvokeScript("fn2");
int i2 = arr2.length;
MessageBox.Show(i2.ToString()); // unless fn3 is called you get...
/*
System.MissingMemberException was unhandled by user code
Message=Error while invoking length.
Source=System.Dynamic
StackTrace:
at System.Dynamic.ComRuntimeHelpers.CheckThrowException(Int32 hresult, ExcepInfo& excepInfo, UInt32 argErr, String message)
at CallSite.Target(Closure , CallSite , ComObject )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
*/
};
}
}

更新

如果 WebBrowser 控件使用 Internet Explorer 版本 9(...该控件使用机器上的 IE 版本),似乎(见评论)此行为已得到修复。在这种情况下,我只能假设 IE9 'Chakra' JavaScript 引擎对旧的 js 引擎做了一些额外/不同的事情。

关于reflection - 在 C# 4 中使用动态类型访问 javascript 对象的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5278275/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com