My question is more C# than Unity, but it relies on a Unity specific delegate, also, sorry if the title is not that clear to what I'm trying to do.
I have implemented a simple event manager which uses a dictionary of <EventName,UnityEvent<object>>.
It works great for what I want, but as it encapsulates a UnityEvent<object> it converts my parameters to object instead of their concrete classes.
I've tried doing the following to be able to register the delegate for the events using the concrete type parameter.
Created an interface and BaseEventData class:
public interface IEventData {}
public abstract class BaseEventData : IEventData {}
Created a custom UnityEvent for this type parameter
[Serializable]
public class CustomDataEvent<T> : UnityEvent<T> where T : IEventData {}
Then I have my dictionary:
protected internal Dictionary<EventName, CustomDataEvent<IEventData>> CustomEventDictionary;
What I want to be able to do is:
EventManager.StartListening<DummyEventData>(EventName.DummyEvent, DummyEventData data => Method(data));
So that my method/delegate can use DummyEventData as the parameter type instead of IEventData/object and then need to cast it to DummyEventData.
What I've tried doing on my register method:
public static void StartListening<T>(EventName eventName, UnityAction<T> listener) where T : IEventData
{
if (Instance.CustomEventDictionary.TryGetValue(eventName, out var thisEvent))
{
thisEvent.AddListener(listener);
}
else
{
thisEvent = new CustomDataEvent<IEventData>();
thisEvent.AddListener(listener);
Instance.CustomEventDictionary.Add(eventName, thisEvent);
}
}
However, this is not possible, the compiler says that UnityAction<T> is not assignable to UnityAction<IEventData>, I've read about covariance and contravariance which seems to be the issue here, but as this involves UnityAction I could not implement the solution I found on this question, is there a way, if any, to achieve what I'm trying to?