2012-09-30 25 views
2

我已經爲我的WPF應用程序(這是代碼的衍生物here)編寫了一個簡單的介體。是否可以更改此代碼,以便可以推斷泛型方法參數?

public class Messenger 
{ 
    private IDictionary<Type, IList<MessageObserver>> observers; 

    public Messenger() 
    { 
     observers = new Dictionary<Type, IList<MessageObserver>>(); 
    } 

    public IDisposeObserver AddObserver<TMessageType>(Action<TMessageType> handler) 
     where TMessageType : Message { } 

    protected abstract void RemoveObserver<TMessageType>(Action<TMessageType> handler) 
     where TMessageType : Message { } 

    public abstract void PostMessage<TMessageType>(TMessageType message) 
     where TMessageType : Message { } 
} 

Message只是一個空類,它提供一個基類爲經由Messenger張貼的所有消息。這個想法是你會從這個類派生出來創建一個具有相關數據的特定消息類(有點像EventArgs)。

我的實現不同的地方在於我想要移除觀察者的方式。我希望能夠指定時,他們應該以聲明的方式去除,沿着線:

MessengerInstance.AddObserver<LoginMessage>(HandleLogin) 
    .RemoveObserverWhen(message => message.LoginResult == LoginResult.Successful); 

RemoveObserverWhen方法採用Predicate<T>其中T應該在AddObserver方法中指定的信息類型。

這裏的想法是,您可以指定在註冊觀察者本身的同一位置移除觀察者的邏輯。然後,Messenger類將在消息處理程序運行後檢查謂詞,並在謂詞計算結果爲true時刪除消息處理程序和刪除處理程序。

每個消息處理程序可以有任意數量的刪除處理程序,所以我將它打包在一個名爲MessageObserver的類中。

public class MessageObserver : IDisposeObserver 
{ 
    private IList<object> disposalHandlers; 

    public MessageObserver(object observer) 
    { 
     Observer = observer; 
     disposalHandlers = new List<object>(); 
    } 

    public object Observer { get; private set; } 

    public IList<object> DisposalHandlers 
    { 
     get { return disposalHandlers; } 
    } 

    public IDisposeObserver RemoveObserverWhen<T>(Predicate<T> predicate) 
     where T : Message 
    { 
     disposalHandlers.Add(predicate); 
     return this; 
    } 
} 

MessageObserver實現IDisposeObserver其提供RemoveObserverWhen方法。

public interface IDisposeObserver 
{ 
    IDisposeObserver RemoveObserverWhen<T>(Predicate<T> predicate) 
     where T : Message; 
} 

的這裏的想法是,一個IDisposeObserver實例可以返回,這樣方法可以鏈接。

這一切工作,我有下面的代碼在我的視圖模型:

MessengerInstance.AddObserver<LoginMessage>(HandleLogin) 
    .RemoveObserverWhen<LoginMessage>(message => message.LoginResult == LoginResult.Successful) 
    .RemoveObserverWhen<LoginMessage>(SecondDisposalHandler); 

我的問題是,如果這僅適用於我指定(在這種情況下LoginMessage)泛型參數調用RemoveObserver方法時。我希望能夠以該帖子開頭描述的方式調用這些方法。

我想我需要以某種方式返回通用IDisposeObserver,但如果我有這樣的變化,則MessageObserver要作出通用,然後爲Messenger類是不通用的,我不能指定的約束。

所以我的問題是,我的代碼是否可以更新,以便我在調用RemoveObserverWhen方法時不必指定消息類型,還是必須使用我當前的解決方案?

注意:我知道還有其他的實現可用,但我這樣做是爲了幫助我理解c#中面向對象的設計原則和泛型,所以請不要指向其他實現的方向。

回答

3

我想我需要以某種方式返回一個通用的IDisposeObserver,但如果我做了這個改變,那麼MessageObserver必須是通用的,然後我不能指定約束,因爲Messenger類是非泛型的。

你可能希望有一個非通用MessageObserver基類,它包含了所有類型的中性部分,然後一個通用的一個它實現了一個通用的IDisposeObserver<T>。然後,您可以更改AddObserver以返回通用IDisposeObserver<T>,但將該字典保留爲MessengerIDictionary<Type, IList<MessageObserver>>。所以,僅僅是明確的,你必須:當你有執行IDiposeObserver<T>.RemoveObserverWhen方法

public interface IDisposeObserver<T> 
{ 
    IDisposeObserver<T> RemoveObserverWhen(Predicate<T> predicate) 
     where T : Message; 
} 

public abstract class MessageObserver { ... } 

public class MessageObserver<T> : MessageObserver, IDisposeObserver<T> { ... } 

問題然後是 - 你可能需要字典的名單內只投每個項目IObserver<T>。那時你會知道T,並且你會知道你已經適當地填充了列表。

當然,如果這是你要與觀察員做只有的事情,你可以只保留一個IDictionary<Type, IList<object>>代替,而不用費心具有兩種不同MessageObserver類。這實際上取決於你是否從非通用項目中獲得任何價值。

相關問題