为什么我的JavaScript数组不能转换为适当的类型?

时间:2013-02-22 18:41:35

标签: c# javascript .net silverlight htmlbridge

我在通过HTMLBridge将JavaScript数组和字典类型对象传递给托管代码中的方法时遇到了一些麻烦。 Microsoft article detailing this topic和网络周围的信息让我无处可去。

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

  

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

     

at System.Windows.Hosting.ScriptingInterface.GetScriptParamValueForType(ScriptParam)   scriptParam,Type desiredType)

     

在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&amp; pResult,ExceptionInfo&amp; pExcepInfo)

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

这些尝试是否是上述文章中对信息的错误解释的结果?或者我的实现是不正确的?

附录:

我知道用ScriptObject .getProperty()完成我想要的方法,但如果可能的话,我想处理具体的确切类型。更不用说它返回本机类型,String或ScriptObject这一事实,如果键控值不能作为前两者之一取消装箱。我不愿意减少在一个任意嵌套的对象上反复调用它,直到我到达本机类型。

2 个答案:

答案 0 :(得分:1)

似乎是那个

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

实际上是

类型
object []

而不是字典类型。

您的代码正在尝试将数组转换为字典,这将无法工作。

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

我担心你不得不把它投到

object[]

然后像

一样处理它
Dictionary<string,object> cur;
foreach(object o in objArray)
{
   cur = (Dictionary<string,object>) o;

}

答案 1 :(得分:1)

再看一下链接的文章,我认为引用的文本是指在createObjectcreateManagedObject创建托管对象之后发生的编组操作。

所以这样的课程:

[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显式或隐式注册,并且传递的值必须是createObjectcreateManagedObject调用所产生的对象别名(createObject)或类型(createManagedObject)。
  3. 如果我所做的任何陈述不正确,请随时纠正我。