2016-07-27 6 views
0

Ich habe einen Eventhandler in C# Umsetzung einige Probleme wurden mit ich nicht in einer Liste Action<T> zu Action<object> für die Lagerung zu werfen scheinen kann.MyClass Casting <T> auf MyClass <object> C#

private readonly IList<Action<object>> listeners; 

public EventHandler() { 
    listeners = new List<Action<object>>(); 
} 

public void RegisterListener<T>(Action<T> listener) where T : class { 
     Listeners.Add((Action<object>)listener); 
    } 

private void ReciveEvent(object evt) { 
     if (evt != null) 
      Listeners.Where(l => l.GetGeneric(0). 
      IsAssignableFrom(evt.GetType())). 
      AsParallel().ForAll(l => l(evt)); 
    } 

bekomme ich nur ein Guss Ausnahme:

Unable to cast object of type 'System.Action`1[Events.SendTestEvent]' to type 'System.Action`1[System.Object]'. 

Events.SendTestEvent <- My current test object... it is just a class with a single property and no parent(besides obj) 
+3

Warum definieren nicht 'T' auf Klassenebene, so dass' listeners' kann als 'IList >' deklariert werden. dann musst du nicht casten. – sstan

+1

@ststan ah, weil ich zu einem Ereignis jeder Art gerne hätte, so IList > könnte sowohl eine Aktion und Aktion enthalten. Code, den ich dafür benutze. http://hastebin.com/betiquyavi.coffee –

+0

Es könnte hilfreich sein, die Frage zu bearbeiten, um einzuschließen, wie Sie beabsichtigen, 'Listeners' zu verwenden. Es ist mir nicht sofort klar, wie nützlich es ist, eine Liste von "Action " zu haben. – sstan

Antwort

0

Was Sie versuchen, ein Action<T> in eine Action<object> ist zu tun, werfen, was nicht möglich ist. Sie können eine neue Aktion machen, die die Aktion durch die Methode übergeben löst und wie diese in die Liste einfügen:

public void RegisterListener<T>(Action<T> listener) where T : class 
{ 
    Action<object> wrappingAction = (arg)=> 
    { 
     var castArg = arg as T; 
     if(castArg != null) 
     { 
      listener(castArg); 
     } 
    }; 

    Listeners.Add(wrappingAction);  
} 

Hinweis: Dies wird nur die Zuhörer auslösen, wenn das Objekt der akzeptierten Parameter gegossen werden Typ, dies jedoch ziemlich ineffizient ist (wie Sie für jeden Zuhörer für diese Art hören Gießen würde)

+1

Oh ich sehe, also gibt es kein Konzept von "unchecked" wie in Java? Danke das sieht gut aus. Wie könnte ich später aus der Liste entfernen, wenn ich so gewickelt? http://hastebin.com/eyufojiseq.xml –

+0

@TheMineBench Wenn Sie in Bezug auf Ausnahmen sprechen, ist das nicht, was hier passiert: das 'as' Schlüsselwort wird versuchen zu wirken und wenn es nicht kann, dann wird null zurückgeben statt eine Ausnahme auslösen – konkked

+0

https://github.com/TheExerosisGaming/EventFramework/blob/master/src/main/java/me/exerosis/event/EventManager.java#L21 Ich glaube, ich verstehe nicht wirklich, was Generika in C# sind . Sie scheinen Laufzeit zu sein, anstatt nur entfernt zu werden. Gibt es eine standardmäßige Möglichkeit, generische Ereignisse wie diese zu behandeln? –

3

ein Action<object> ist eine Methode, die alles akzeptieren kann wie es Parameter ist. Ein Action<T> ist ein Objekt, das nur ein Objekt vom Typ T als Parameter akzeptieren kann. Wenn Sie einen Action<T> als Action<object> behandeln könnten, könnten Sie ein Objekt übergeben, das nicht vom Typ T ist, aber die Aktion kann keine Objekte akzeptieren, die nicht vom Typ T sind. Der Compiler verbietet Ihnen dies.

0

Sie können dies nicht tun, weil es nicht sicher wäre. Es würde Ihnen ermöglichen, zu tun

Sie könnten den gegebenen Handler in einen umwandeln, der beim Aufruf z.

public void RegisterListener<T>(Action<T> listener) where T : class { 
    Listeners.Add(o => { listener((T)o); }); 
} 
Verwandte Themen