在 Xamarin 中绑定多维数组

Binding multi-dimentional arrays in Xamarin

我正在尝试绑定一个 属性,我知道它是一个(多维)NSArray 持有 NSArray 个对象,而这些对象又持有 [=15= 的实例].我已经绑定了这样的方法:

[Export ("options")]
NSObject[][] Options { get; set; }

当我构建我的绑定时,我在为上述 属性 生成的 class 中收到以下错误。

来自对 NSArray.FromNSObjects 的生成调用:

(1) Argument `#1` cannot convert 'Foundation.NSObject[][]' expression to type 'Foundation.NSObject[]'.
(2) Error CS1502: The best overloaded method match for `Foundation.NSArray.FromNSObjects(params Foundation.NSObject[])' has some invalid arguments (CS1502)

来自对 NSArray.ArrayFromHandle<Foundation.NSObject[]> 的生成调用:

(1) Error CS0311: The type `Foundation.NSObject[]' cannot be used as type parameter `T' in the generic type or method `Foundation.NSArray.ArrayFromHandle<T>(System.IntPtr)'. There is no implicit reference conversion from `Foundation.NSObject[]' to `ObjCRuntime.INativeObject' (CS0311)

错误一直指的是编译器无法在 Foundation.NSObject[][]Foundation.NSObject[] 之间进行转换。我不明白为什么这会是个问题,NSArrayNSObject 的子 class,那么为什么它不能将第二个数组维度视为 NSObject

(我知道我有其他选择,例如将选项绑定为 NSObject[],或者只是 NSObject,但我宁愿尽可能保证类型安全。)

我认为出现这个问题是因为FromNSObjectsArrayFromHandle方法无法处理多维数组的转换,但我不完全确定。

我设法通过从我的绑定文件 (ApiDefinition.cs) 中删除 Options 的绑定并在部分 class 中手动绑定 属性 来解决这个问题.

我写了两个方法在多维 NSArrayNSObject[][] 之间转换。

    private NSArray NSArraysFromTwoDimentionalArray(NSObject[][] firstDimension) {
        NSMutableArray nsFirstDimension = new NSMutableArray ();

        foreach (NSObject[] secondDimention in firstDimension) {
            NSMutableArray nsSecondDimension = new NSMutableArray ();
            foreach (NSObject nsObj in secondDimention) {
                nsSecondDimension.Add (nsObj);
            }
            nsFirstDimension.Add (nsSecondDimension);
        }

        NSArray toReturn = (NSArray)nsFirstDimension.Copy ();

        nsFirstDimension.Dispose ();

        return toReturn;
    }

    private NSObject[][] TwoDimentionalArrayFromArrayOfNSArrays (NSArray[] nsFirstDimension) {
        NSObject[][] firstDimension = new NSObject[nsFirstDimension.Length][];

        int i = 0;
        foreach (NSArray nsSecondDimension in nsFirstDimension) {
            NSObject[] secondDimension = NSArray.ArrayFromHandle<NSObject> (nsSecondDimension.Handle);

            firstDimension[i] = secondDimension;
            i++;
        }

        return firstDimension;
    }

然后我使用上面的转换方法来实现我的绑定。

    public virtual NSObject[][] Options {
        [Export ("options")]
        get {

            NSArray[] firstDimension;
            if (IsDirectBinding) {
                firstDimension = NSArray.ArrayFromHandle<NSArray> (ApiDefinition.Messaging.IntPtr_objc_msgSend (this.Handle, Selector.GetHandle ("options")));
            } else {
                firstDimension = NSArray.ArrayFromHandle<NSArray> (ApiDefinition.Messaging.IntPtr_objc_msgSendSuper (this.SuperHandle, Selector.GetHandle ("options")));
            }

            return TwoDimentionalArrayFromArrayOfNSArrays (firstDimension);
        }


        [Export ("setOptions:")]
        set {
            if (value == null)
                throw new ArgumentNullException ("value");

            var multiNSArray = NSArraysFromTwoDimentionalArray (value);

            if (IsDirectBinding) {
                ApiDefinition.Messaging.void_objc_msgSend_IntPtr (this.Handle, Selector.GetHandle ("setOptions:"), multiNSArray.Handle);
            } else {
                ApiDefinition.Messaging.void_objc_msgSendSuper_IntPtr (this.SuperHandle, Selector.GetHandle ("setOptions:"), multiNSArray.Handle);
            }
            multiNSArray.Dispose ();

        }

    }