I'm trying to implement EventArgs to pass a list of parameters to my messaging system: Question.
I subclassed EventArgs:
public class SingleParameterArgs<T> : EventArgs
{
public T arg1;
public SingleParameterArgs(T _arg1)
{
arg1 = _arg1;
}
}
Here's the class and method that should accept the EventArgs:
static public class Messenger<TEventArgs> where TEventArgs : EventArgs {
private static Dictionary< string, EventHandler<TEventArgs> > eventTable = new Dictionary< string, EventHandler<TEventArgs> >();
static public void Invoke(string eventType, TEventArgs args) {
EventHandler<TEventArgs> eventHandler;
if (eventTable.TryGetValue(eventType, out eventHandler)) {
if (eventHandler != null)
eventHandler();
}
}
}
Before implementing EventArgs I would invoke a message in the following way:
Messenger<GameEndingType>.Invoke( "end game", GameEndingType.TimeEnded );
But now it looks much longer and much more complicated:
Messenger< SingleParameterArgs<GameEndingType> >.Invoke( "end game", new SingleParameterArgs<GameEndingType>(GameEndingType.TimeEnded) );
Is it possible to make it look shorter? I don't want to type such a long line every time I need to send a message. Maybe I could create a wrapper?
Something like this would be perfect:
Messenger.Invoke("end game", GameEndingType.TimeEnded);
What is the best way to create a uniform wrapper for a random amount of parameters?
Are you happy for your Messenger class to be tied to SingleParameterArgs<T>? If so, you could use:
// Here TEventArgs represents the element type *within* SingleParameterArgs
public static class Messenger<TEventArgs> {
private static
Dictionary<string, EventHandler<SingleParameterArgs<TEventArgs>> eventTable =
new Dictionary<string, EventHandler<SingleParameterArgs<TEventArgs>>();
public static void Invoke(string eventType, TEventArgs args) {
EventHandler<SingleParameterArgs<TEventArgs>> eventHandler;
if (eventTable.TryGetValue(eventType, out eventHandler)) {
if (eventHandler != null) {
eventHandler();
}
}
}
}
Of course you can have both, with a totally general Messenger class (as per your question), and then a SingleParameterMessenger class which delegates to it:
public static class SingleParameterMessenger<TEventArgs> {
public static void Invoke(string eventType, TEventArgs args) {
Messenger<SingleParameterArgs<TEventArgs>>.Invoke(eventType, args);
}
}
Just as an aside, I'm not really sure this is all a good idea anyway - particularly in terms of static registration, which tends to make testing harder, and certainly needs more care in terms of concurrency. (Your code is currently not threadsafe.)
Related
I am trying to add webapi (owin.selfhosting) support to existing C# console app and I have problem with callbacks from the controller. Essentially I need to call a function as a reaction to the http request. I think it's possible with delegates/events, but so far no success.
Update:
Using static event seems to work, I used a standard pattern as described in this video (https://www.youtube.com/watch?v=jQgwEsJISy0) and adding a static keyword before event declaration. But mixing static delegate with non static subscriber probably is not the best practice.
Code sample :
//appcontroller.cs
public class AppController : ApiController
{ public delegate void EventHandler(object source, EventArgs args);
public static event EventHandler EventRecived;
protected virtual void OnEventRecived(string arg)
{
if( EventRecived != null)
{
EventRecived(this, arg);
}
}
[Route("api/{arg}")]
public void GetFoo(string arg)
{
/*
*
*/
OnEventRecived();
}
}
//program.cs
class Program
{ static void Main(string[] args)
{ WebApp.Start<Startup>(url: baseAddress);
SomeClass obj = new SomeClass();
AppController.EventHandler+=obj.OnRecivedEvent;
while (true)
{ //do work
}
}
}
class SomeClass
{ public SomeClass() {}
public void OnRecivedEvent(object sender, EventArgs e)
{
Foo(e);
}
public void Foo(string arg)
{
//do something
Console.WriteLine("request of "+arg);
}
}
Example for http get request to http://localhost:8080/api/holy_grail
Console output >>request of holy_grail
Would like to ask how to make a dictionary with delegate.
The idea is:
Have a console based command defined by "/"
use dictionary to store command and del that will invoke the function i need.
What i have so far: I managed to do same by creating events
delegate void CmdHandler(string[] cmdArgs);
class CMDReader
{
public event CmdHandler _Print;
public event CmdHandler _Help;
private char cmdChar;
}
cmdReader._Print += new CmdHandler(Print);
void Print(string[] args)
but I am looking for a way to manage it without event. I figured I can do so with dictionary but not sure how to do it.
You can add the delegates to a Dictionary, and then using an indexer key (I've just assumed the name of the command here) to Invoke the appropriate action. The problem with this pattern however is the loose typing on the arguments (All string[], with implied knowledge about the meaning of each), and the restriction on a common return type from all methods (currently void).
public class CMDReader
{
delegate void CmdHandler(string[] cmdArgs); // Or Action<string[]>
private readonly IDictionary<string, CmdHandler> _commands;
public CMDReader()
{
_commands = new Dictionary<string, CmdHandler>
{
{
"Print", Print
},
{
"Help", Help
},
};
}
public void InvokeCommand(string command, string[] args)
{
if (_commands.ContainsKey(command))
{
_commands[command].Invoke(args);
// OR (_commands[command])(args);
}
else
{
Console.WriteLine("I don't know that command ...");
}
}
private void Print(string[] args)
{
// Implementation
}
private void Help(string[] args)
{
// Implementation
}
}
I'm not sure if this has been asked before, but I really didn't know how to look for it, as I am not exactly sure what this thing / what I'm trying to do is exactly called...
I have an delegate-based messaging generic system that I use in Unity3D - taken from here.
[UA Crosslink]
It is used like this:
// Writing an event listener
void OnSpeedChanged(float speed)
{
this.speed = speed;
}
// Registering an event listener
void OnEnable()
{
Messenger<float>.AddListener("speed changed", OnSpeedChanged);
}
// Unregistering an event listener
void OnDisable()
{
Messenger<float>.RemoveListener("speed changed", OnSpeedChanged);
}
The problem I'm having, is that the code is currently very un-DRY (there's a lot of copy paste), and I want to DRY it, by hopefully parametrizing it, making it more generic.
I will post the relevant code - Please note that you don't really have to understand the code in detail and what's its doing, in order to answer.
Here's a class that does stuff behind the scene:
static internal class MessengerInternal
{
static public Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();
static public readonly MessengerMode DEFAULT_MODE = MessengerMode.REQUIRE_LISTENER;
static public void OnListenerAdding(string eventType, Delegate listenerBeingAdded)
{
if (!eventTable.ContainsKey(eventType)) {
eventTable.Add(eventType, null);
}
Delegate d = eventTable[eventType];
if (d != null && d.GetType() != listenerBeingAdded.GetType()) {
throw new ListenerException(string.Format("Attempting to add listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being added has type {2}", eventType, d.GetType().Name, listenerBeingAdded.GetType().Name));
}
}
static public void OnListenerRemoving(string eventType, Delegate listenerBeingRemoved)
{
if (eventTable.ContainsKey(eventType)) {
Delegate d = eventTable[eventType];
if (d == null) {
throw new ListenerException(string.Format("Attempting to remove listener with for event type {0} but current listener is null.", eventType));
}
else if (d.GetType() != listenerBeingRemoved.GetType()) {
throw new ListenerException(string.Format("Attempting to remove listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being removed has type {2}", eventType, d.GetType().Name, listenerBeingRemoved.GetType().Name));
}
}
else {
throw new ListenerException(string.Format("Attempting to remove listener for type {0} but Messenger doesn't know about this event type.", eventType));
}
}
static public void OnListenerRemoved(string eventType)
{
if (eventTable[eventType] == null) {
eventTable.Remove(eventType);
}
}
static public void OnBroadcasting(string eventType, MessengerMode mode)
{
if (mode == MessengerMode.REQUIRE_LISTENER && !eventTable.ContainsKey(eventType)) {
throw new BroadcastException(string.Format("Broadcasting message {0} but no listener found.", eventType));
}
}
}
Now, I have generic messenger classes, that have either one, two, three or even no arguments - So the user could choose a suitable event handler to subscribe to an event.
Here's the version, that takes no generic arguments:
// No parameters
static public class Messenger {
private static Dictionary<string, Delegate> eventTable = MessengerInternal.eventTable;
static public void AddListener(string eventType, Callback handler) {
MessengerInternal.OnListenerAdding(eventType, handler);
eventTable[eventType] = (Callback)eventTable[eventType] + handler;
}
static public void RemoveListener(string eventType, Callback handler) {
MessengerInternal.OnListenerRemoving(eventType, handler);
eventTable[eventType] = (Callback)eventTable[eventType] - handler;
MessengerInternal.OnListenerRemoved(eventType);
}
static public void Broadcast(string eventType) {
Broadcast(eventType, MessengerInternal.DEFAULT_MODE);
}
static public void Broadcast(string eventType, MessengerMode mode) {
MessengerInternal.OnBroadcasting(eventType, mode);
Delegate d;
if (eventTable.TryGetValue(eventType, out d)) {
Callback callback = d as Callback;
if (callback != null) {
callback();
} else {
throw MessengerInternal.CreateBroadcastSignatureException(eventType);
}
}
}
}
Here's the version that takes one arg, (I just copy paste and add a T):
// One parameter
static public class Messenger<T> {
private static Dictionary<string, Delegate> eventTable = MessengerInternal.eventTable;
static public void AddListener(string eventType, Callback<T> handler) {
MessengerInternal.OnListenerAdding(eventType, handler);
eventTable[eventType] = (Callback<T>)eventTable[eventType] + handler;
}
static public void RemoveListener(string eventType, Callback<T> handler) {
MessengerInternal.OnListenerRemoving(eventType, handler);
eventTable[eventType] = (Callback<T>)eventTable[eventType] - handler;
MessengerInternal.OnListenerRemoved(eventType);
}
static public void Broadcast(string eventType, T arg1) {
Broadcast(eventType, arg1, MessengerInternal.DEFAULT_MODE);
}
static public void Broadcast(string eventType, T arg1, MessengerMode mode) {
MessengerInternal.OnBroadcasting(eventType, mode);
Delegate d;
if (eventTable.TryGetValue(eventType, out d)) {
Callback<T> callback = d as Callback<T>;
if (callback != null) {
callback(arg1);
} else {
throw MessengerInternal.CreateBroadcastSignatureException(eventType);
}
}
}
}
As you might have already guessed, the one that takes two args, I just copy paste again, and add another generic type, like <T, U> etc.
This is the part that I'm trying to eliminate - But yet I have no idea how.
More accurately, what I'm looking for is: Only one Messenger class, but yet I am able to do:
Messenger<float>.Subscribe("player dead", OnDead);
Messenger<int, bool>.Subscribe("on something", OnSomething);
Messenger<bool, float, MyType>.Subscribe( stuff );
Or, (doesn't really matter which)
Messenger.Subscribe<float> ("player dead", OnDead);
You got the idea...
How can I do that, how can I write a generic messenger, that when I want to add yet another generic arg, I don't have to copy-paste and write a whole other version, just cause I needed an extra arg?
Thanks a lot!
You have a messenger but you don't seem to be sending any messages! You are trying to send the contents without a proper envelope. Wrap the values you want to send out in a class that represents your actual message and you can then subscribe to the type of the message which will contain all the values you were trying to send.
public class PlayerSpeedChangedMessage {
public Guid PlayerId { get; set; }
public int OldSpeed { get; set; }
public int NewSpeed { get; set; }
}
public class MyMessageHandler {
public MyMessageHandler() {
Messenger<PlayerSpeedChangedMessage>.Subscribe(OnDead);
}
HandleSpeedChange(PlayerSpeedChangedMessage message) {
// Do stuff with the message
}
}
I think for C# developers that Message class on the wiki is a little out-moded. C# and even Unity itself has a fairly nice messaging system already in place (As long as your needs aren't too complex). Check out SendMessage and BroadcastMessage.
I have a class that goes like this:
public static class Messenger<T>
{
private static readonly Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();
public static void DoSomethingWithEventTable() //Somehow fills eventTable
public static void Clear()
{
eventTable.Clear();
}
}
Now, I called DoSomethingWithEventTable two times somewhere in my program, like this:
Messenger<int>.DoSomethingWithEventTable();
Messenger<float>.DoSomethingWithEventTable();
I want to clear eventTable for every Messenger<T>. How should I do it? Should I call Clear for every type that I have put in generics, like this:
Messenger<int>.Clear();
Messenger<float>.Clear();
Or will it be enough to do something silly like this once:
Messenger<string>.Clear();
UPD: Basic experiments show that I should clear the Messenger for every used T. Now could somebody come with better design for the classes?
The more detailed version of what I am using now:
static public class Messenger<T>
{
private static readonly Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();
static public void AddListener(string eventType, Callback<T> handler)
{
// Obtain a lock on the event table to keep this thread-safe.
lock (eventTable)
{
// Create an entry for this event type if it doesn't already exist.
if (!eventTable.ContainsKey(eventType))
{
eventTable.Add(eventType, null);
}
// Add the handler to the event.
eventTable[eventType] = (Callback<T>)eventTable[eventType] + handler;
}
}
static public void RemoveListener(string eventType, Callback<T> handler)
{
// Obtain a lock on the event table to keep this thread-safe.
lock (eventTable)
{
// Only take action if this event type exists.
if (eventTable.ContainsKey(eventType))
{
// Remove the event handler from this event.
eventTable[eventType] = (Callback<T>)eventTable[eventType] - handler;
// If there's nothing left then remove the event type from the event table.
if (eventTable[eventType] == null)
{
eventTable.Remove(eventType);
}
}
}
}
static public void Invoke(string eventType, T arg1)
{
Delegate d;
// Invoke the delegate only if the event type is in the dictionary.
if (eventTable.TryGetValue(eventType, out d))
{
// Take a local copy to prevent a race condition if another thread
// were to unsubscribe from this event.
Callback<T> callback = (Callback<T>)d;
// Invoke the delegate if it's not null.
if (callback != null)
{
callback(arg1);
}
}
}
static public void Clear()
{
eventTable.Clear();
}
}
It is also important that I have another classes Messenger (non-generic, yeah) and Messenger<T,M>, and maybe someday I would even need something like Messenger<T,M,N>, etc.
Each Messenger<T> type will have it's own copy of eventTable so you will need to call Clear() for every different T you have used.
As shown by this test:
[TestFixture]
public class Tests
{
static class MyClass<T>
{
public static List<int> Member = new List<int>();
}
[Test]
public void StaticTest()
{
var m1 = MyClass<int>.Member;
var m2 = MyClass<string>.Member;
Assert.AreNotSame(m1, m2);
}
}
Since
private static readonly Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();
does not depend on <T>, create a static "handler" for all event tables.
IE
public static class TableHandler {
ICollection<Dictionary<string, Delegate>> tables = new List<Dictionary<string, Delegate>>();
public void Add(Dictionary<string, Delegate> item)
{
tables.Add(item);
}
public void Clear()
{
foreach (var item in tables) item.Clear();
tables.Clear();
}
}
and ensure that DoSomethingWithEventTable() adds the event table to the TableHandler.
Might not be the best overall solution, but it helps you keep track of the tables with the current design.
EDIT:
I tried to google for a way to find all generic variants of a static class, but I did not find a way. Does anyone know of a way to do that?
I have two very similar classes that do essentially the same thing. The only difference is in a callback handler provided to an instance of each class. The callback handlers are different and they are accepted with different parameters. I would like to generalize most of the code from these classes into a base class. Any ideas on how to generalize the delegate code intelligently? I'm on .NET 2.0
Note: I read this very useful blog on inheritance with delegates and articles on covariance and contravariance with delegates, but I still don't see how that knowledge can be applied here.
public class A
{
public delegate void AHandler(string param1, string param2);
public void AcceptHandler(string param3, AHandler handler);
public void InvokeHandler(string forParam1, string forParam2);
// the rest is same
}
public class B
{
public delegate void BHandler(int param1);
public void AcceptHandler(int param2, int param3, int param4, BHandler handler);
public void InvokeHandler(int forParam1);
// the rest is same
}
EDIT: "the rest" of the code is exact same, except calls to the delegate methods that have different signatures. Something like this:
public void StartListening()
{
Timer timer = new Timer(CheckForChanges, null, 0, 1000);
}
private void CheckForChanges()
{
// pull changes, and pass different params to InvokeHandler()
}
Why not set it up like this:
Edit: I've updated to include the methods from your edit.
public abstract class AbstractBase {
// "the rest"
public void StartListening() {
Timer timer = new Timer(CheckForChanges, null, 0, 1000);
}
protected abstract void CheckForChanges();
}
public class A : AbstractBase {
public delegate void AHandler(string param1, string param2);
public void AcceptHandler(string param3, AHandler handler);
public void InvokeHandler(string forParam1, string forParam2);
protected override void CheckForChanges() {
//Do stuff for this version of the class
}
}
public class B : AbstractBase {
public delegate void BHandler(int param1);
public void AcceptHandler(int param2, int param3, int param4, BHandler handler);
public void InvokeHandler(int forParam1);
protected override void CheckForChanges() {
//Do stuff for this version of the class
}
}
This way, you'll have all your code that is the same in a single class, and then the individual classes A and B can have whatever form of the methods you need.
Or are you looking for a way to invoke the delegates generically irrespective of which class?
ie. Something like:
AbstractBase ab = new A();
ab.InvokeDelegate();