2016-01-14 58 views
2

我正在使用Weak Events in .Net, the easy way中的代碼來處理對可觀察集合的監視更改。該代碼幾個月以來一直沒有任何問題。我最近更新到一臺新電腦。在完成所有設置並從存儲庫中取出代碼後,我遇到了一個奇怪的問題。代碼不再有效!在舊計算機上工作的ReactiveExtension現在失敗了

這裏是我的代碼的相關部分,這一切都發生在構造函數中:

public class PurchaseOrderReceipt : BaseEntity 
{ 
    /// <summary> 
    ///  Initializes a new instance of the <see cref="PurchaseOrderReceipt" /> class. 
    /// </summary> 
    public PurchaseOrderReceipt() 
    { 
     this.ReceiptItems = new ObservableCollection<PurchaseOrderItemReceipt>(); 
     this.DateReceived = DateTime.Now; 

     this.ReceiptItems.ObserveCollectionChanged() 
      .SubscribeWeakly(this, (target, eventArgs) => target.ReceiptItemsChanged()); 
    } 

拋出異常與以下錯誤消息SubscribeWeakly行:的ArgumentException:onNext必須指向一個靜態方法,否則訂閱仍然會對目標有強烈的參考

我可以通過創建PurchaseOrderReceipt實例來重新創建LinqPad中的問題。

如果我在LinqPad中寫了一個簡單的類來反映PurchaseOrderReceipt類中的設置,它仍然有效。

LinqPad代碼:

void Main() 
{ 
    var x = new Test(); 
    x.ReceiptItems.Add(new PurchaseOrderItemReceipt()); 

} 

public class Test:BaseEntity 
{ 
    public ObservableCollection<PurchaseOrderItemReceipt> ReceiptItems {get; set;} 

    public Test() 
    { 
     this.ReceiptItems = new ObservableCollection<PurchaseOrderItemReceipt>(); 
     this.ReceiptItems.ObserveCollectionChanged().SubscribeWeakly(this,(target, eventargs) => target.TestChanged()); 
    } 

    private void TestChanged() 
    { 
     "Changed!".Dump(); 
    } 
} 

改變了!打印在結果窗口中。

以下是頂部鏈接的CustomReactiveExtension類。

public static class CustomReactiveExtension 
    { 
     public static IObservable<EventPattern<NotifyCollectionChangedEventArgs>> ObserveCollectionChanged(this INotifyCollectionChanged collection) 
     { 
      return Observable.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
       handler => (sender, e) => handler(sender, e), 
       handler => collection.CollectionChanged += handler, 
       handler => collection.CollectionChanged -= handler); 
     } 

     public static IDisposable SubscribeWeakly<T, TTarget>(this IObservable<T> observable, TTarget target, Action<TTarget, T> onNext) where TTarget : class 
     { 
      var reference = new WeakReference(target); 

      if (onNext.Target != null) 
      { 
       throw new ArgumentException("onNext must refer to a static method, or else the subscription will still hold a strong reference to target"); 
      } 

      IDisposable subscription = null; 
      subscription = observable.Subscribe(item => 
      { 
       var currentTarget = reference.Target as TTarget; 
       if (currentTarget != null) 
       { 
        onNext(currentTarget, item); 
       } 
       else 
       { 
        subscription.Dispose(); 
       } 
      }); 

      return subscription; 
     } 
    } 

任何想法?

回答

1

我不是100%確定的,但我的猜測是,無論是不同版本的編譯器或不同的編譯選項,都會導致您的lambda被編譯爲實例方法而不是靜態方法。

以最簡單的解決辦法是明確地實現一個靜態方法來作爲你的onNext回調,即:

private static void OnReceiptItemsChanged(PurchaseOrderReceipt target, 
    EventPattern<NotifyCollectionChangedEventArgs> eventPattern) 
{ 
    // TODO Do something here 
} 

然後用SubscribeWeakly像這樣:

this.ReceiptItems.ObserveCollectionChanged().SubscribeWeakly(this, OnReceiptItemsChanged); 

現在不管其中你使用的編譯器或哪個編譯選項的回調總是一個靜態方法。

+0

工作就像一個魅力!謝謝! –

相關問題