解决Xamarin.Android绑定第三方库时类型丢失的问题(一)
现象
今天在做一个第三方库绑定时,遇到如下情况:
![](http://image.suihanime.com/解决Xamarin.Android绑定第三方库时类型丢失的问题(一)_00001.jpg)
摘取其中一段代码如下:
/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);
}
查阅官方文档,发现此类问题的可能情况有:
![](http://image.suihanime.com/解决Xamarin.Android绑定第三方库时类型丢失的问题(一)_00002.jpg)
![](http://image.suihanime.com/解决Xamarin.Android绑定第三方库时类型丢失的问题(一)_00003.jpg)
通过分析,我认为这个问题是第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)
我跟进到出现问题的地方:
// 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的字段,我们应该用不着也不应该访问这个字段,于是我直接添加了移除这个字段绑定的代码如下:
<remove-node path="/api/package[@name='com.xsj.crasheye']/class[@name='ActionTransactionStop']/field[@name='status']" />
reBuild,ok!
参考文献
- 原文作者:岁寒
- 原文链接:http://www.suihanime.com/post/Xamarin/%E8%A7%A3%E5%86%B3Xamarin.Android%E7%BB%91%E5%AE%9A%E7%AC%AC%E4%B8%89%E6%96%B9%E5%BA%93%E6%97%B6%E7%B1%BB%E5%9E%8B%E4%B8%A2%E5%A4%B1%E7%9A%84%E9%97%AE%E9%A2%98%E4%B8%80/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。