Xamarin.android MonoDroid中从Java.Lang.Object到本机CLR类型的类型转换

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

如何将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.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()

以上所有答案都是正确的,但我发现对于我的案例来说,最简单的方法是将对象变成Java.Lang.object的子类

例如,我正在用Monotouch编写一个Android应用程序,使用ExpandableListAdapter模仿iOS中UITableView的概念,它需要与UITableViewCells等效的元素,因此我从Java.Lang.Object中对cell对象进行了子类化,从而实现了ExpandableListAdapter的子类,如

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>();