Skip to content

Commit

Permalink
Prevent AddListener from adding the same delegate
Browse files Browse the repository at this point in the history
We found that ensuring that delegate instances are unique was a good way
to prevent odd, difficult to detect behavior.  This behavior is present
to some extent in BaseSignal, so it seems to make sense to add it to
Signal's implementation as well.
  • Loading branch information
bejeweledpair committed May 5, 2014
1 parent 6a0cc3f commit 3bad4a8
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 7 deletions.
101 changes: 101 additions & 0 deletions StrangeIoC/scripts/strange/.tests/extensions/signal/TestSignal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,107 @@ public void TestMultipleCallbacks()
Assert.AreEqual(testInt + 1, testValue);
}

[Test]
public void AddListener_SignalWithNoTypeGivenSameCallbackMultipleTimes_ExpectsDelegateCalledOnlyOnce()
{
Signal signal = new Signal();
simpleInt = 0;

signal.AddListener(SimpleSignalCallback);
signal.AddListener(SimpleSignalCallback);

signal.Dispatch();

Assert.AreEqual(1, simpleInt);
}

private int simpleInt;
private void SimpleSignalCallback()
{
simpleInt++;
}

[Test]
public void AddListener_SignalWithOneTypeGivenSameCallbackMultipleTimes_ExpectsDelegateCalledOnlyOnce()
{
Signal<int> signal = new Signal<int>();
simpleInt = 1;

signal.AddListener(OneArgSignalCallback);
signal.AddListener(OneArgSignalCallback);

signal.Dispatch(simpleInt);

Assert.AreEqual(1, testValue);
}

[Test]
public void AddListener_SignalWithTwoTypesGivenSameCallbackMultipleTimes_ExpectsDelegateCalledOnlyOnce()
{
Signal<int,int> signal = new Signal<int,int>();
int firstInt = 1;
int secondInt = 2;

signal.AddListener(TwoArgCallback);
signal.AddListener(TwoArgCallback);

signal.Dispatch(firstInt, secondInt);
int expected = firstInt + secondInt;
Assert.AreEqual(expected, this.testValue);
}

private void TwoArgCallback(int arg1, int arg2)
{
this.testValue += arg1 + arg2;
}

[Test]
public void AddListener_SignalWithThreeTypesGivenSameCallbackMultipleTimes_ExpectsDelegateCalledOnlyOnce()
{
Signal<int,int,int> signal = new Signal<int, int, int>();
int firstInt = 1;
int secondInt = 2;
int thirdInt = 3;

signal.AddListener(ThreeArgCallback);
signal.AddListener(ThreeArgCallback);

signal.Dispatch(firstInt, secondInt, thirdInt);
int expected = firstInt + secondInt + thirdInt;

Assert.AreEqual(expected, this.testValue);

}

private void ThreeArgCallback(int arg1, int arg2, int arg3)
{
this.testValue += arg1 + arg2 + arg3;
}

[Test]
public void AddListener_SignalWithFourTypesGivenSameCallbackMultipleTimes_ExpectsDelegateCalledOnlyOnce()
{
Signal<int, int, int, int> signal = new Signal<int, int, int, int>();
int firstInt = 1;
int secondInt = 2;
int thirdInt = 3;
int fourthInt = 4;

signal.AddListener(FourArgCallback);
signal.AddListener(FourArgCallback);

signal.Dispatch(firstInt, secondInt, thirdInt, fourthInt);
int expected = firstInt + secondInt + thirdInt + fourthInt;

Assert.AreEqual(expected, this.testValue);

}

private void FourArgCallback(int arg1, int arg2, int arg3, int arg4)
{
this.testValue += arg1 + arg2 + arg3 + arg4;
}

[Test]
public void TestRemoveListener()
{
Expand Down
52 changes: 45 additions & 7 deletions StrangeIoC/scripts/strange/extensions/signal/impl/Signal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace strange.extensions.signal.impl
{
Expand All @@ -74,8 +76,16 @@ public class Signal : BaseSignal
{
public event Action Listener = delegate { };
public event Action OnceListener = delegate { };
public void AddListener(Action callback) { Listener += callback; }
public void AddOnce(Action callback) { OnceListener += callback; }

public void AddListener(Action callback)
{
if (!Listener.GetInvocationList().Contains(callback))
{
Listener += callback;
}
}

public void AddOnce(Action callback) { OnceListener += callback; }
public void RemoveListener(Action callback) { Listener -= callback; }
public override List<Type> GetTypes()
{
Expand All @@ -94,8 +104,15 @@ public void Dispatch()
public class Signal<T> : BaseSignal
{
public event Action<T> Listener = delegate { };
public event Action<T> OnceListener = delegate { };
public void AddListener(Action<T> callback) { Listener += callback; }
public event Action<T> OnceListener = delegate { };

public void AddListener(Action<T> callback)
{
if (!Listener.GetInvocationList().Contains(callback))
{
Listener += callback;
}
}
public void AddOnce(Action<T> callback) { OnceListener += callback; }
public void RemoveListener(Action<T> callback) { Listener -= callback; }
public override List<Type> GetTypes()
Expand All @@ -119,7 +136,14 @@ public class Signal<T, U> : BaseSignal
{
public event Action<T, U> Listener = delegate { };
public event Action<T, U> OnceListener = delegate { };
public void AddListener(Action<T, U> callback) { Listener += callback; }

public void AddListener(Action<T, U> callback)
{
if (!Listener.GetInvocationList().Contains(callback))
{
Listener += callback;
}
}
public void AddOnce(Action<T, U> callback) { OnceListener += callback; }
public void RemoveListener(Action<T, U> callback) { Listener -= callback; }
public override List<Type> GetTypes()
Expand All @@ -144,7 +168,14 @@ public class Signal<T, U, V> : BaseSignal
{
public event Action<T, U, V> Listener = delegate { };
public event Action<T, U, V> OnceListener = delegate { };
public void AddListener(Action<T, U, V> callback) { Listener += callback; }

public void AddListener(Action<T, U, V> callback)
{
if (!Listener.GetInvocationList().Contains(callback))
{
Listener += callback;
}
}
public void AddOnce(Action<T, U, V> callback) { OnceListener += callback; }
public void RemoveListener(Action<T, U, V> callback) { Listener -= callback; }
public override List<Type> GetTypes()
Expand All @@ -170,7 +201,14 @@ public class Signal<T, U, V, W> : BaseSignal
{
public event Action<T, U, V, W> Listener = delegate { };
public event Action<T, U, V, W> OnceListener = delegate { };
public void AddListener(Action<T, U, V, W> callback) { Listener += callback; }

public void AddListener(Action<T, U, V, W> callback)
{
if (!Listener.GetInvocationList().Contains(callback))
{
Listener += callback;
}
}
public void AddOnce(Action<T, U, V, W> callback) { OnceListener += callback; }
public void RemoveListener(Action<T, U, V, W> callback) { Listener -= callback; }
public override List<Type> GetTypes()
Expand Down

0 comments on commit 3bad4a8

Please sign in to comment.