1

我在通过 HTMLBridge 将 JavaScript 数组和字典类型对象传递给我的托管代码中的方法时遇到了一些问题。Microsoft文章中详细介绍此主题和网络的信息让我无处可去。

使用链接文章中的以下信息:

NET Framework 属性或类型为对象的输入参数在按值封送至目标 .NET Framework 属性或输入参数时使用以下启发式方法进行转换:

JavaScript 数组转换为object[].

JavaScript 字典被转换为Dictionary<string,object>.

...我尝试以多种方式将数组和字典对象传递给我的托管代码,但没有成功:

Javascript:

var array = [{key: 1}, {key: 2}, {key: 3}];
silverlight_domElement.content.testObject.testMethod(array);

C#(尝试#1):

[ScriptableMember]

//THROWS CONVERSION EXCEPTION HERE
public void testMethod(Dictionary<string,object>[] arrayParam) 
{
    //...
}

C#(尝试#2):

[ScriptableMember]
public void testMethod(object arrayParam) 
{
    //THROWS CONVERSION EXCEPTION HERE
    Dictionary<string, object>[] arr = (Dictionary<string, object>[])arrayParam; 
}

C#(尝试#3):

[ScriptableMember]
public void testMethod(ScriptObject arrayParam)
{
    //THROWS CONVERSION EXCEPTION HERE
    Dictionary<string, object>[] arr = 
      arrayParam.ConvertTo<Dictionary<string, object>[]>();

}

例外的形式是(其中“TARGET TYPE”是由显式或隐式强制转换(包括Object[])产生的对象的预期类型:

SCRIPT16389:System.ArgumentException:无法将此对象转换为指定类型TARGET TYPE。参数名称:targetType

在 System.Windows.Browser.ScriptObject.ConvertTo(类型 targetType,布尔 allowSerialization)

在 System.Windows.Hosting.ScriptingInterface.GetScriptParamValueForType(ScriptParam scriptParam,键入所需类型)

在 System.Windows.Hosting.ScriptingInterface.ConvertFromScriptParams(ParameterInfo[] 参数,ScriptParam[] args)

在 System.Windows.Browser.ManagedObjectInfo.ScriptMethod.Invoke(ManagedObject obj,InvokeType invokeType,ScriptParam[] args)

在 System.Windows.Browser.ManagedObjectInfo.Invoke(ManagedObject obj,InvokeType invokeType,String memberName,ScriptParam [] args)

在 System.Windows.Hosting.ManagedHost.InvokeScriptableMember(IntPtr pHandle,Int32 nMemberID,Int32 nInvokeType,Int32 nArgCount,ScriptParam [] pArgs,ScriptParam & pResult,ExceptionInfo & pExcepInfo)

(类似的尝试将字典对象作为 传递给 C# Dictionary<string, object>)。

这些尝试是否是对上述文章及其他文章中信息的误解的结果?还是我的实现根本不正确?

附录:

我知道用ScriptObject.getProperty()完成我想要的方法,但如果可能的话,我想处理具体的、精确的类型。更不用说如果键值不能像前两者一样拆箱,它会返回本机类型、String 或 ScriptObject。我讨厌被简化为在任意嵌套的对象上反复调用它,直到我到达一个本机类型。

4

2 回答 2

1

再看一下链接的文章后,我相信引用的文本是指在托管对象上由createObjector创建后发生的编组操作createManagedObject

所以像这样的类:

[ScriptableType]
public class TestClass
{
    public object arrayObj;
    public object dicObj;
    public TestClass sibling;

    public TestClass(){}
    public void testMethod(TestClass testClassObj)
    {
                               //Assuming argument came from Javascript
                               //& arrayObj and dicObj were assigned an 
                               //Array and dictionary-obj respectively

         testClassObj.arrayObj; //Formal type: Object. Actual type: object[]
         testClassObj.dicObj;   //Formal type: Object. Actual type: 
                                //                     Dictionary<string, object>
    }
}

Silverlight 应用程序使用如下:

private void Application_Startup(object sender, StartupEventArgs e)
{
    this.RootVisual = new MainPage();
    HtmlPage.RegisterCreatableType("TestClass", typeof(TestClass));
    HtmlPage.RegisterScriptableObject("scripTestClassObj", new TestClass());
}

可以在客户端这样使用:

var testClassObj = silverlight_domElement.content
                    .services.CreateObject("TestClass");
testClassObj.arrayObj = [1,2,3];  
testClassObj.dicObj = {key: 1};  

silverlight_domElement.content.scripTestClassObj.testMethod(testClassObj);

//"sibling"'s arrayObj and dicObj types will have actual types
//of object[] and Dictionary<string, object> respectively
silverlight_domElement.content.scripTestClassObj.sibling = testClassObj;

换句话说,它与讨论的功能无关。

在我的问题的上下文中,这意味着将非原始 Javascript 值传递给托管代码需要遵守以下准则之一:

  1. 目标属性或方法参数的类型必须是ScriptObject(或Object,因为这是它派生的类)。
  2. 目标属性或方法参数的类型必须显式或隐式注册到 HtmlPage.RegisterCreatableType,并且传递的值必须是使用注册别名 ( ) 或类型 ( ) 的createObjector调用产生的对象。createManagedObjectcreateObjectcreateManagedObject

如果我所做的任何陈述不正确,请随时纠正我。

于 2013-02-22T21:50:58.283 回答
1

好像是这样

[{key: 1}, {key: 2}, {key: 3}]

实际上是类型

object []

而不是字典类型。

您的代码试图将数组转换为字典,这将永远无法工作。

澄清一下,因为您的顶级对象是一个数组,因此是对象 [],JSON 解析器不够聪明,无法知道数组中每个元素的各个类型。

恐怕你将不得不将它投射到

object[]

然后像处理它

Dictionary<string,object> cur;
foreach(object o in objArray)
{
   cur = (Dictionary<string,object>) o;

}
于 2013-02-22T18:53:25.297 回答