Xamarin.android MonoDroid中从Java.Lang.Object到本机CLR类型的类型转换
如何将Java.Lang.Object强制转换为某些本机类型 例如: ListView适配器包含本机类型消息的实例。当我试图从ListView获取SelectedItem时,它返回消息类型的实例,并将其转换为Java.Lang.Object,但我找不到将Java.Lang.Object转换回消息的解决方案Xamarin.android MonoDroid中从Java.Lang.Object到本机CLR类型的类型转换,xamarin.android,Xamarin.android,如何将Java.Lang.Object强制转换为某些本机类型 例如: ListView适配器包含本机类型消息的实例。当我试图从ListView获取SelectedItem时,它返回消息类型的实例,并将其转换为Java.Lang.Object,但我找不到将Java.Lang.Object转换回消息的解决方案 var message = (Message)list.SelectedItem; // throws Error 5 Cannot convert type 'Java.Lang
var message = (Message)list.SelectedItem;
// throws Error 5 Cannot convert type 'Java.Lang.Object' to 'Message'
请提供帮助。经过长时间的调试,我们找到了解决方案:
public static class ObjectTypeHelper
{
public static T Cast<T>(this Java.Lang.Object obj) where T : class
{
var propertyInfo = obj.GetType().GetProperty("Instance");
return propertyInfo == null ? null : propertyInfo.GetValue(obj, null) as T;
}
}
公共静态类ObjectTypeHelper
{
公共静态T Cast(这个Java.Lang.Object obj),其中T:class
{
var propertyInfo=obj.GetType().GetProperty(“实例”);
返回propertyInfo==null?null:propertyInfo.GetValue(obj,null)作为T;
}
}
用法示例:
var message = list.GetItemAtPosition(e.Position).Cast<Message>();
bundle.PutInt("Message", message.ID);
var message=list.GetItemAtPosition(e.Position).Cast();
bundle.PutInt(“Message”,Message.ID);
经过仔细的sdk研究,我们发现MonoDroid集成扩展可用于此目的:
public static TResult JavaCast<TResult>(this Android.Runtime.IJavaObject instance)
where TResult : class, Android.Runtime.IJavaObject
Member of Android.Runtime.Extensions
publicstatictresultjavacast(这个Android.Runtime.IJavaObject实例)
其中TResult:class,Android.Runtime.IJavaObject
Android.Runtime.Extensions的成员
对于泛型集合,正确的答案是使用JavaList,它是一个Java.Lang.Object,并且还实现了IList。但这肯定涉及到更多的工作。这实际上只是Java的ArrayList实现的适配器 您可以尝试JavaCast方法(大多数视图都实现了这一点)(未经测试):
var message=list.SelectedItem.JavaCast
public override Java.Lang.Object GetChild(int position, int childPosition)
等等。从微调器获取本机类型最不神奇的方法是调用
message = ((ArrayAdapter<Message>)list.Adapter).GetItem(list.SelectedItemPosition);
message=((ArrayAdapter)list.Adapter).GetItem(list.SelectedItemPosition);
这是我的工作:
public class HolderHelper<T> : Java.Lang.Object {
public readonly T Value;
public HolderHelper (T value)
{
this.Value = value;
}
}
公共类持有者帮助:Java.Lang.Object{
公共只读T值;
公共持有者帮助者(T值)
{
这个。值=值;
}
}
测试:
chkFileName.Tag=新持有人帮助人(项目);
LinkInfo link=(chkFileName.tagas HolderHelper).Value;
我使用了上面答案中的代码,对我来说效果很好
public static class ObjectTypeHelper
{
public static T Cast<T>(this Java.Lang.Object obj) where T : class
{
var propertyInfo = obj.GetType().GetProperty("Instance");
return propertyInfo == null ? null : propertyInfo.GetValue(obj, null) as T;
}
}
公共静态类ObjectTypeHelper
{
公共静态T Cast(这个Java.Lang.Object obj),其中T:class
{
var propertyInfo=obj.GetType().GetProperty(“实例”);
返回propertyInfo==null?null:propertyInfo.GetValue(obj,null)作为T;
}
}
我就是这样用的
var selectedLocation = locationSpinner.SelectedItem.Cast<Location>();
var selectedLocation=locationSpinner.SelectedItem.Cast();
如果由于某些原因无法获取GetChildAtPosition,我可以从spinner获取我的location对象,将对象序列化为json字符串,然后将字符串反序列化回本机类。注释人(已编辑到答案中):此扩展严重受限,您不能应用于泛型集合类型,如
List
或t[]
,其中t本身是类型参数。建议的扩展方法的优点是,它适用于未实现ijavaObjects的类型,即扩展方法可以完美地工作。这正是我需要的伟大的解决方案。为我工作。
var selectedLocation = locationSpinner.SelectedItem.Cast<Location>();