在C#4中使用动态类型访问javascript对象的属性 [英] Accessing properties of javascript objects using type dynamic in C# 4

查看:674
本文介绍了在C#4中使用动态类型访问javascript对象的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这个对象是一个数组,传递给托管代码从JavaScript,我希望得到它的长度属性作为一个int。



我知道我错过了一些奇怪的,因为我没有得到一个'不包含



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



例如



此失败

  dynamic com = comObject; 
int i = com.length; // RTBE这里。

This Works

 类型t​​ype = comObject.GetType(); 
int i =(int)type.InvokeMember(length,BindingFlags.GetProperty,null,comObject,null);

* Update *



经过大量测试后,我将这种奇怪性减少到了多维数组的情况。
所讨论的com对象是从html文档传递到托管代码的参数。对于所有的意图和目的,对象有时在JavaScript中看起来像这样。

  var x = [a1,a2 a3]; 

当这样的数组到托管代码时,我能够使用类型动态中。 (即,这里第一个示例失败实际上工作)。但是,如果它是一个多维数组,如JavaScript中的以下结构。

  var y = [[b1 ,b2,b3],a2,a3]; 

然后,当我试图动态访问它的length属性时,注意,在这种情况下,我仍然可以通过反射访问长度。在我看来,由于某种原因,当一个多维数组用作动态类型时,length属性不能正确映射...



在我的例子中完成解决(!?)这是添加一个'length_'属性到数组,如此之前传递它。

  var y = [[b1,b2,b3],a2,a3]; 
y.length_ = y.length

现在在托管代码中,我可以按预期访问此属性,而不会出错。远不理想,但似乎工作...

  dynamic com = comObject; 
int i = com.length_; // 3!



进一步更新



好吧,所以看起来,以及length属性对象索引也失去了动态类型。

  dynamic com = comObject; // js array var x = [1,2]; 
int i = com [0]; // MissingMemberException - 调用[PROPERTYGET,DISPID(0)]时出错。
int i = com [0]; // MissingMemberException - 调用[PROPERTYGET,DISPID(0)]时出错。

起作用

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


解决方案

多维数组的长度属性在c#通过类型动态,除非,似乎你已经使用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

//如果我在这里调用fn3,那么arr2.length *可用作int i2下面!
////webBrowser1.Document.InvokeScript(\"fn3); // 4

dynamic arr2 = webBrowser1.Document.InvokeScript(fn2);
int i2 = arr2.length;
MessageBox.Show(i2.ToString()); //除非fn3被调用你得到...
/ *
System.MissingMemberException未被用户代码处理
Message =调用长度时出错。
Source = System.Dynamic
StackTrace:
在System.Dynamic.ComRuntimeHelpers.CheckThrowException(Int32 hresult,ExcepInfo& excepInfo,UInt32 argErr,String message)
在CallSite.Target
在CallSite.Target(Closure,CallSite,Object)
在$ System.Dynamic.UpdateDelegates.UpdateAndExecute1的
(CallSite站点,T0 arg0) System.Dynamic.UpdateDelegates.UpdateAndExecute1 [T0,TRet](CallSite site,T0 arg0)
* /
};
}
}

更新 >

似乎(见评论),如果WebBrowser控件使用Internet Explorer版本9(...控件使用机器上的IE版本),此行为是固定的。我只能假设IE9'Chakra'JavaScript引擎在这种情况下对旧js引擎执行额外/不同的操作。


I define a com object as a dynamic type in c# I am able to call methods quite easily. However when I try to access a property on the same object I get an invalid cast exception.

The object in question is an array, passed to managed code from JavaScript, and I wish to get the length property of it as an int.

I know I am missing something odd because I am not getting a 'does not contain a definition' exception and I can access the property easily using reflection/InvokeMember.

Why can I not convert the length property of the dynamic type to an int?

For example

This Fails

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

This Works

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

* Update *

After a lot of testing I have narrowed this oddness to cases of multi-dimensional arrays. The com object in question is a parameter passed from a html document to managed code. For all intents and purposes the object sometimes looks like this in JavaScript.

var x = ["a1", "a2", "a3"];

When an array like this comes to managed code I am able to get the length AOK using the type dynamic. (i.e. the first example here that fails actually works). However, if it is a multi-dimensional array such as the following structure in JavaScript.

var y = [["b1", "b2", "b3"], "a2", "a3"];

Then I get an error when trying to access its length property dynamically. Note, I can still access the length via reflection in this case. It seems to me that for some reason the length property does not get correctly mapped when a multidimensional array is used as a dynmaic type...

In my case what I have done to solve(!?) this is add a 'length_' property to the array like so before passing it.

var y = [["b1", "b2", "b3"], "a2", "a3"];
y.length_ = y.length;

Now in managed code I can accesses this property as expected without error. Far from ideal but seems to work...

   dynamic com = comObject;
   int i = com.length_; // 3!

Further Update

Ok, so it seems that as well as the length property the objects index gets lost to the dynamic type as well. Again it is accessible via reflection though...

Fails

   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)].

Works

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

解决方案

In simple terms you can't access the length property of a multi-dimensional array in c# via the type dynamic unless, it seems, you have used the length property in JavaScript first...

The simple test below shows this very clearly. I hope this saves someone else the head scratching I have been having over the last day or so.

[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)
            */             
        };
    }
}

update

It seems (see comments) that this behaviour is fixed if the WebBrowser control uses version 9 of Internet Explorer (...the control uses the version of IE on the machine). I can only presume that the IE9 'Chakra' JavaScript engine is doing something extra/different to the old js engine in this case.

这篇关于在C#4中使用动态类型访问javascript对象的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆