C
C#5mo ago
Killers0992

✅ Get delegate from event

I got class
public static class Events
{
public static PlayerEvents Player { get; } = new PlayerEvents();
}
public static class Events
{
public static PlayerEvents Player { get; } = new PlayerEvents();
}
and PlayerEvents class contains
public class PlayerEvents
{
public event Event<PlayerLeftServer> Leaving;

public event Event<PlayerLeftServer> Left;
}
public class PlayerEvents
{
public event Event<PlayerLeftServer> Leaving;

public event Event<PlayerLeftServer> Left;
}
I want to get delegate from Leaving/Left event but seems like while trying to get value its null? idk
foreach (var property in typeof(Events).GetProperties(BindingFlags.Public | BindingFlags.Static))
{
foreach (var ev in property.PropertyType.GetEvents())
{
FieldInfo evField = property.PropertyType.GetField(ev.Name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.GetField);

// GetValue returns null
Debug.Log(evField.GetValue(property.GetValue(null, null)));
}
}
foreach (var property in typeof(Events).GetProperties(BindingFlags.Public | BindingFlags.Static))
{
foreach (var ev in property.PropertyType.GetEvents())
{
FieldInfo evField = property.PropertyType.GetField(ev.Name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.GetField);

// GetValue returns null
Debug.Log(evField.GetValue(property.GetValue(null, null)));
}
}
14 Replies
Killers0992
Killers09925mo ago
Someone will ask why I didnt add like method in PlayerEvents class which just for example Uses Leaving?.Invoke(args) what I want to create single static method for calling any event with that argument without needing to create x amount of methods just for calling these events something like
static void Invoke<T>(T ev) where T : BaseEvent
{
/// Checks dictionary and gets that specific delegate and uses Invoke(ev);
}
static void Invoke<T>(T ev) where T : BaseEvent
{
/// Checks dictionary and gets that specific delegate and uses Invoke(ev);
}
cap5lut
cap5lut5mo ago
when u add/remove an event listener to the event, the underlying event delegate will change, if its value is null, it means that there is currently no listener listening on the event if u look at the lowered code of
public class C {
public event Action<int> A;
}
public class C {
public event Action<int> A;
}
this becomes more obvious:
public class C
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private Action<int> m_A;

public event Action<int> A
{
[CompilerGenerated]
add
{
Action<int> action = this.A;
while (true)
{
Action<int> action2 = action;
Action<int> value2 = (Action<int>)Delegate.Combine(action2, value);
action = Interlocked.CompareExchange(ref this.A, value2, action2);
if ((object)action == action2)
{
break;
}
}
}
[CompilerGenerated]
remove
{
Action<int> action = this.A;
while (true)
{
Action<int> action2 = action;
Action<int> value2 = (Action<int>)Delegate.Remove(action2, value);
action = Interlocked.CompareExchange(ref this.A, value2, action2);
if ((object)action == action2)
{
break;
}
}
}
}
}
public class C
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private Action<int> m_A;

public event Action<int> A
{
[CompilerGenerated]
add
{
Action<int> action = this.A;
while (true)
{
Action<int> action2 = action;
Action<int> value2 = (Action<int>)Delegate.Combine(action2, value);
action = Interlocked.CompareExchange(ref this.A, value2, action2);
if ((object)action == action2)
{
break;
}
}
}
[CompilerGenerated]
remove
{
Action<int> action = this.A;
while (true)
{
Action<int> action2 = action;
Action<int> value2 = (Action<int>)Delegate.Remove(action2, value);
action = Interlocked.CompareExchange(ref this.A, value2, action2);
if ((object)action == action2)
{
break;
}
}
}
}
}
and if u look at the Delegate.Remove(Delegate, Delegate) method's documentation, it says:
A new delegate with an invocation list formed by taking the invocation list of source and removing the last occurrence of the invocation list of value, if the invocation list of value is found within the invocation list of source. Returns source if value is null or if the invocation list of value is not found within the invocation list of source. Returns a null reference if the invocation list of value is equal to the invocation list of source or if source is a null reference.
the highlighted code basically means if the invocation list result would be empty afterwards, it returns null
Killers0992
Killers09925mo ago
seems like without doing something like this its not possible really to easily create single method to invoke x event?
No description
cap5lut
cap5lut5mo ago
yeah, seems like the only way. note that usually events are only invocable by the owning type and not from "the outside". so u would have to write these InvokeLeft and alike methods anyway if u want to make that possible
Killers0992
Killers09925mo ago
idk if this method is way slower than last one
No description
Killers0992
Killers09925mo ago
but somehow works yea first method is better for sure
Killers0992
Killers09925mo ago
No description
cap5lut
cap5lut5mo ago
im not really sure what that is supposed to solve
Killers0992
Killers09925mo ago
idk I just wanted to have 1 method to execute any event which in that class
cap5lut
cap5lut5mo ago
its not thread safe, has a lot of dictionary overhead and doesnt handle exceptions per registered listener as ur extension method would do
Killers0992
Killers09925mo ago
thanks for help I will just use my extension method
cap5lut
cap5lut5mo ago
if ur question is answered, please $close the thread 🙂
MODiX
MODiX5mo ago
Use the /close command to mark a forum thread as answered
reflectronic
reflectronic5mo ago
there is no need to use GetInvocationList. there is no need for InvokeEvent at all you just do Leaving?.Invoke(arg)