我在c#中将com对象定义为动态类型我能够非常轻松地调用方法。 但是,当我尝试访问同一对象上的属性时,我得到一个无效的强制转换异常。

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

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

为什么我不能将动态类型的length属性转换为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"];

当像这样的数组进入托管代码时,我可以使用动态类型获得长度AOK。 (即这里的第一个例子实际上无效)。 但是,如果它是一个多维数组,例如JavaScript中的以下结构。

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

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

在我的情况下,我已经做了解决(!?)这是在传递它之前向数组添加'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

#1楼 票数:3 已采纳

简单来说,你不能通过动态类型访问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引擎做了额外/不同的事情。

  ask by community wiki translate from so

未解决问题?本站智能推荐:

5回复

当属性名来自另一个源时,如何在C#4中动态设置类的属性而不使用反射(带动态)

我正在运行时构建/更新EntityFramework EntityObject。 我想设置实体类的属性,属性名称和值来自另一个源。 所以我这样做; 那么,我怎样才能摆脱“t.GetProperty(values [j] .EntityPropertyName).SetValue(loc
5回复

如何在C#4.0中访问动态类型的count属性?

我有follow方法返回一个表示IEnumerable<'a> ('a =匿名类型)的动态对象: 我希望能够访问此IEnumerable匿名类型的Count属性。 我正在尝试使用以下代码访问上述方法,但它失败了: dynamic关键字如何运作? 如何访问IEnume
1回复

Objective-C字典作为属性/方法的访问

在我的obj-c类中,我有一个将字符串映射到对象的字典。 现在,不要做: 我想要做: 可能吗? 当然,这假定(a)字典键是有效的标识符名称; (b)没有同名的“真实”属性/方法(这可能会调用真实方法)。
7回复

如何在不使用反射的情况下通过名称动态访问属性?

起初我在使用: 其中firstSort.Item2是属性的字符串名称。 但是,由于未排序列表中项目的数量增加,因此性能显着下降。 (如我所料) 有没有一种方法可以不用反射呢? 蛮力方法将做如下事情: 我正在寻找可以完成上述行为的东西,而不必在接口中的所有不同属性中进行硬编码。
13回复

如何检查c#中动态匿名类型上是否存在属性?

我有一个匿名类型对象,我从我想检查该对象上存在的属性的方法中作为动态接收。 我将如何实现 IsSettingExist ?
3回复

在运行时动态添加C#属性

我知道有一些问题可以解决这个问题,但答案通常遵循推荐字典或参数集合的方式,这在我的情况下不起作用。 我正在使用一个通过反射工作的库来对具有属性的对象做很多聪明的事情。 这适用于定义的类以及动态类。 我需要更进一步,并按照以下方式做一些事情: 该库可以很好地处理动态变量类型,并手动分配属性。 但是我不
2回复

如何获取没有自定义类类型的一个类的属性

我有一个Person类: 我需要一个通用的解决方案来获取Person类的所有属性,而不是自定义类类型的属性。 表示选择Code , Title属性。 如何在没有自定义类类型的情况下选择所有属性? ( Code , Title )
3回复

为什么反射不在Struct中设置属性?

打印的第一个值是32,而第二个值是0.没有异常抛出