2015-02-24 12 views
1

我已經繼承了這個Xamarin.Android應用程序,它有幾個問題。Xamarin.Android:先前插入ArrayAdapter的項目再次找不到

一個特殊的bug涉及ArrayAdapter<ProductListObject>,其中ProductListObject是在子項目(即Android,Windows Phone和iOS)之間共享的常見POCO;它只是有幾個屬性(例如Id)和覆蓋(.NET)Equals()方法來實現結構相等:

public class ProductListObject 
{ 
    public long Id { get; set; } 

    public override bool Equals(object obj) 
    { 
     if (!(obj is ProductListObject)) 
     { 
      return false; 
     } 

     return Id == (obj as ProductListObject).Id; 
    } 
} 

的問題是,每當我把這個ProductListObject實例在ArrayAdapter,我不能再次找到它,即使它們具有相同的Id

var p1 = new ProductListObject { Id = 1 }; 
var p2 = new ProductListObject { Id = 1 }; 

var areEqual = p1.Equals(p2); // returns True, as expected 

var productAdapter = new ArrayAdapter<ProductListObject>(this, 0, new[] { p1 }); 
var position = productAdapter.GetPosition(p2); // returns -1 >:(

我的問題是:我有什麼做的,使我的POCO的工作與依賴於Java equals()方法Xamarin.Android類型,內部(like ArrayAdapter; which delegates to List.indexOf(Object))?

我曾嘗試:

  • 驗證了相應的Java版本工作正常(它)
  • 壓倒GetHashCode()(沒關係,如我所料)
  • 一派,檢查關於實施Equals()(我發現沒有什麼特別相關的)信息的Xamarin文檔

謝謝, Jan

回答

0

我一樣馬特 - [R建議,並創造了從Java.Lang.Object和代表繼承實際.NET對象的代理:

public class JavaObject<TValue> : Java.Lang.Object 
{ 
    public readonly TValue Value; 

    internal JavaObject(TValue value) 
    { 
     Value = value; 
    } 

    public override bool Equals(Java.Lang.Object that) 
    { 
     if (!(that is JavaObject<TValue>)) 
     { 
      return false; 
     } 

     return Value.Equals((that as JavaObject<TValue>).Value); 
    } 

    public override int GetHashCode() 
    { 
     return Value.GetHashCode(); 
    } 
} 

這不配合我的平臺無關的POCO對Android的實施,再加上它並不強迫我鎖定一些剛性繼承樹,這總是一個加號。

應用很簡單:

var p1 = new JavaObject<ProductListObject>(new ProductListObject { Id = 1 }); 
var p2 = new JavaObject<ProductListObject>(new ProductListObject { Id = 1 }); 

var areEqual = p1.Equals(p2); // returns True, as expected 

var productAdapter = new ArrayAdapter<JavaObject<ProductListObject>>(this, 0, new[] { p1 }); 
var position = productAdapter.GetPosition(p2); // returns 0! 
0

Android.Widget.ArrayAdapter中使用時,看起來像.NET對象被封裝在Java.Lang.Object中。因此,productAdapter.GetPosition(...)調用中使用的比較方法實際上是用於包裝Java.Lang.Object的java Equals(Java.Lang.Object o)方法。

爲了使ProductListObject決心同指數當兩個對象具有相同的Id,使ProductListObjectJava.Lang.Object得出,覆蓋Equals(Java.Lang.Object)並將其轉發到.NET Equals(System.Object)方法:

public class ProductListObject : Java.Lang.Object 
{ 
    public long Id { get; set; } 

    public override bool Equals(object obj) // Inherited from System.Object. 
    { 
     if (!(obj is ProductListObject)) 
     { 
      return false; 
     } 

     return Id == (obj as ProductListObject).Id; 
    } 

    public override bool Equals (Java.Lang.Object o) // Inherited from Java.Lang.Object. 
    { 
     return this.Equals (o as System.Object); 
    } 
} 

如果可以的話「T繼承Java.Lang.ObjectProductListObject,另一個選擇是實現自己的代理類:

public class ProductListObject 
{ 
    public long Id { get; set; } 

    public override bool Equals(System.Object obj) 
    { 
     if (!(obj is ProductListObject)) 
     { 
      return false; 
     } 

     return Id == (obj as ProductListObject).Id; 
    } 
} 

public class JavaProxy: Java.Lang.Object 
{ 
    public Object Object { get; private set; } 

    public JavaProxy(System.Object o) 
    { 
     Object = o; 
    } 

    public override bool Equals (Java.Lang.Object o) 
    { 
     var proxy = o as JavaProxy; 
     if (o != null) { 
      return Object.Equals (proxy.Object); 
     } 
     return base.Equals (o); 
    } 
} 

// ... 

var productAdapter = new ArrayAdapter<JavaProxy>(this, 0, new[] { new JavaProxy(p1) }); 
var position = productAdapter.GetPosition(new JavaProxy(p2)); 

它不像第一種方法那樣乾淨,但它也可以工作。

+0

是的,但會配合我的POCO對Xamarin.Android(這是在Windows手機和iOS子項目也使用)。 – 2015-02-25 08:36:32

+1

這是一個Xamarin.Forms應用程序嗎?如果不是,另一種選擇是創建自己的'Java.Lang.Object'代理,將其equals方法轉發給.NET對象equals方法。 – matthewrdev 2015-02-25 11:33:54

相關問題