2015-04-29 44 views
1

我正在尋找適當和優雅的方式來創建具有類型化回調的介體/訂戶體系結構。傳遞代理作爲中介/訂戶模式的參數

讓我們假設我有一個「事件」,即代表一類:

public class E 
{ 
    public delegate void SomethingHappened (float a, int b); 
    public delegate void ProgressFinished (int[] c); 
} 

現在我想創建一個Mediator類,將註冊回調到這些代表和調度回調與提供的參數:

public class Mediator 
{ 
    public static void Register (???, Action callback) 
    { 
     // supplied delegate += callback 
    } 

    public static void Dispatch (???, params object[] list) 
    { 
     // executing supplied delegate with params: delegate(list) 
    } 
} 

所以,我可以用它的方式如下:

// Class A: 
Mediator.Register (E.SomethingHappened, OnSomethingHappened); 
private void OnSomethingHappened (float a, int b) 
{ 
    //.......... 
} 

// Class B: 
Mediator.Dispatch (E.SomethingHappened, 0.1f, 'qwe'); 

現在牛逼他的問題是我無法將委託作爲參數傳遞給Register或Dispatch。我該如何解決這個問題?

+1

我想你誤會了與會代表。委託*是*回調(或者可以用作它) - 您不會使用委託註冊回調*。也許你實際上是在尋找事件呢? –

+1

我編輯了你的標題。請參閱:「[應該在其標題中包含」標籤「](http://meta.stackexchange.com/questions/19190/)」,其中的共識是「不,他們不應該」。 –

+1

@JonSkeet:我相信OP想基於它的委託類型註冊一個具體的回調方法,但不知道如何將委託類型傳遞給方法 – Groo

回答

1

你應該採取一種不同的方法:讓你的發件人發送消息,並讓你的中介根據它們的類型分派給不同的處理程序。

使用泛型,這將被重構爲:

// handlers should be differentiated by message type 
public class SomethingHappenedMessage 
{ 
    public float A { get; set; } 
    public int B { get; set; } 
} 

public class Mediator 
{ 
    private readonly Dictionary<Type, object> _dict = new Dictionary<Type, object>(); 

    public void Register<Tmessage>(Action<Tmessage> callback) 
    { 
     _dict[typeof(Tmessage)] = callback; 
    } 

    public void Dispatch<Tmessage>(Tmessage msg) 
    { 
     var handler = _dict[typeof(Tmessage)] as Action<Tmessage>; 
     handler(msg); 
    } 
} 

或者,你可能有多個處理程序爲每個消息類型:

public class Mediator 
{ 
    readonly Dictionary<Type, List<object>> _handlersByType = new Dictionary<Type, List<object>>(); 

    public void Register<Tmessage>(Action<Tmessage> callback) 
    { 
     List<object> handlers; 
     if (!_handlersByType.TryGetValue(typeof(Tmessage), out handlers)) 
      _handlersByType[typeof(Tmessage)] = handlers = new List<object>(); 

     handlers.Add(callback); 
    } 

    public void Dispatch<Tmessage>(Tmessage msg) 
    { 
     List<object> handlers; 
     if (!_handlersByType.TryGetValue(typeof(Tmessage), out handlers)) 
      return; 

     foreach (Action<Tmessage> handler in handlers) 
      handler(msg); 
    } 
} 
+0

謝謝,這看起來不錯。似乎我無法進一步減少樣板消息聲明? –

+0

@VincentPride:我想可能有辦法使用反射來剖析委託類型,但是這是迄今爲止最乾淨的方法。您可以在任何地方聲明任何消息類,並在此處註冊其處理程序。此外,爲了更鬆散的耦合,請注意我創建了所有方法實例(與靜態方法相比),以便您可以傳遞中介。 – Groo