Cannot implicitly convert type Action<T>

tobsa

New member
Joined
Jan 5, 2018
Messages
2
Programming Experience
1-3
Hi,

I'm currently writing an event-based messaging system and have encountered a problem. Basically I want to be able to do this:

C#:
// Use a lambda
EventManager.Register<TestEvent1>((@event) => 
{
    //Do something with event
});


// or use a method
EventManager.Register<TestEvent2>(OnTestEvent);
private void OnTestEvent(TestEvent2 @event)
{
    //Do something with event
}

I've reduced the problem so it looks like this:

C#:
public interface IEvent { }
public class TestEvent1 : IEvent {}
public class TestEvent2 : IEvent {}


public class EventManager
{
    private Dictionary<Type, Action<IEvent>> actions = new Dictionary<Type, Action<IEvent>>();


    public void Register<T>(Action<T> @event) where T : IEvent
    {
        actions[typeof(T)] = @event;
    }


    public void Push(IEvent @event)
    {
        actions[@event.GetType()](@event);
    }
}

The problem is in the Register method where the compiler complains that I cannot convert type System.Action<T> to System.Action<IEvent>. Does anybody know a way around this? I.E without changing the Register-method interface.


Thanks
 
Last edited:
Okay, after a bit of experimentation I'v now come up with a solution that works pretty good. If anyone is interested it now looks like this:
C#:
public class Event<T>
{
    public T Content { get; set; }


    public Event(T content)
    {
        Content = content;
    }
}
 
public class EventManager
{
    private Dictionary<Type, List<object>> observers = new Dictionary<Type, List<object>>();


    public void Register<T>(Action<Event<T>> action)
    {
        var type = typeof(T);


        if (!observers.ContainsKey(type))
            observers[type] = new List<object>();
        
        observers[type].Add(action);
    }


    public void Push<T>(T @event)
    {
        foreach (var observer in observers[typeof(T)])
            ((Action<Event<T>>)observer)((new Event<T>(@event)));
    }
}

And usage:
C#:
EventManager.Register<TestEvent>(OnTestEvent);
EventManager.Register<TestEvent>((x) =>
{
    // Do something with event through x.Content
});


EventManager.Push(new TestEvent());
 

Latest posts

Back
Top Bottom