現(xiàn)象
今天在做一個第三方庫綁定時试读,遇到如下情況:
摘取其中一段代碼如下:
/Users/huangboru/myfile/xamarin_workspace/version4/CrashEyeTestPlus/obj/Debug/generated/src/Com.Xsj.Crasheye.ActionError.cs(88,88): Error CS0234: The type or namespace name 'IInterfaceDataType' does not exist in the namespace 'Com.Xsj.Crasheye' (are you missing an assembly reference?) (CS0234) (CrashEyeTestPlus)
錯誤代碼的意思是無法找到IInterfaceDataType類型钟病。
解決過程
為了方便查看綁定的情況酷麦,我新建了一個Android Studio項目裸删,添加這個第三方庫噪径,去看這個類型是什么,看到的情況如下:
package com.xsj.crasheye;
import android.content.Context;
interface InterfaceDataType {
String toJsonLine();
void send(Context var1, NetSender var2, boolean var3);
void send(NetSender var1, boolean var2);
void save(BaseDataSaver var1);
}
查閱官方文檔藏雏,發(fā)現(xiàn)此類問題的可能情況有:
通過分析,我認為這個問題是第4種情況:Java允許一個公開類型去繼承一個非公開的類型作煌,而這在.Net中是不受支持的掘殴。由于綁定生成器無法生成對非公開類型的綁定,自然也就無法準確地綁定其公開的子類粟誓。為了解決這個問題奏寨,我們需要在Metadata.xml文件中將這個非公開的類型聲明為公開類型。
在我的項目中鹰服,我添加的代碼如下:
<attr path="/api/package[@name='com.xsj.crasheye']/interface[@name='InterfaceDataType']" name="visibility">public</attr>
<attr path="/api/package[@name='com.xsj.crasheye']/interface[@name='InterfaceExecutor']" name="visibility">public</attr>
不過問題并沒有完全消除病瞳,還有一個error:
/Users/huangboru/myfile/xamarin_workspace/version4/CrashEyeTestPlus/obj/Debug/generated/src/Com.Xsj.Crasheye.ActionTransactionStop.cs(38,38): Error CS0234: The type or namespace name 'EnumTransactionStatus' does not exist in the namespace 'Com.Xsj.Crasheye' (are you missing an assembly reference?) (CS0234) (CrashEyeTestPlus)
我跟進到出現(xiàn)問題的地方:
// Metadata.xml XPath field reference: path="/api/package[@name='com.xsj.crasheye']/class[@name='ActionTransactionStop']/field[@name='status']"
[Register ("status")]
protected global::Com.Xsj.Crasheye.EnumTransactionStatus Status {
get {
const string __id = "status.Lcom/xsj/crasheye/EnumTransactionStatus;";
var __v = _members.InstanceFields.GetObjectValue (__id, this);
return global::Java.Lang.Object.GetObject<global::Com.Xsj.Crasheye.EnumTransactionStatus> (__v.Handle, JniHandleOwnership.TransferLocalRef);
}
set {
const string __id = "status.Lcom/xsj/crasheye/EnumTransactionStatus;";
IntPtr native_value = global::Android.Runtime.JNIEnv.ToLocalJniHandle (value);
try {
_members.InstanceFields.SetValue (__id, this, new JniObjectReference (native_value));
} finally {
global::Android.Runtime.JNIEnv.DeleteLocalRef (native_value);
}
}
}
對方是一個非公開enum類型,我嘗試像上面一樣公開這個enum悲酷,但不可行套菜。
觀察代碼可知,Xamarin在嘗試綁定一個ActionTransactionStop的status字段设易,我到原生項目中查看這個字段:
public class ActionTransactionStop extends ActionTransaction implements InterfaceDataType {
protected EnumTransactionStatus status;
.......
}
可知這是一個protected的字段逗柴,我們應(yīng)該用不著也不應(yīng)該訪問這個字段,于是我直接添加了移除這個字段綁定的代碼如下:
<remove-node path="/api/package[@name='com.xsj.crasheye']/class[@name='ActionTransactionStop']/field[@name='status']" />
reBuild顿肺,ok戏溺!