Unit Test Event Handler - c#

I got this event handle and how can I do unit test for this
public class MyLearningEvent
{
private event EventHandler _Closed;
public event EventHandler Closed
{
add
{
_Closed -= value;
_Closed += value;
}
remove
{
_Closed -= value;
}
}
public void OnClosed()
{
if (_Closed != null) _Closed(this, EventArgs.Empty);
}
}
Just modified code so that much clear
Thanks

You should not unit test that code. It's a feature which is built into .NET. Your event handling is flawed imho.
add
{
_Closed -= value;
_Closed += value;
}
Probably means that your invokers don't keep track on if they have subscribed or not. That can lead to memory leaks: http://blog.naviso.fr/wordpress/wp-content/uploads/2011/11/MemoryLeaks-English.jpg
A more robust (and thread safe implementation) is:
public class MyLearningEvent
{
public event EventHandler Closed = delegate {};
public void TriggerClosed()
{
Closed(this, EventArgs.Empty);
}
}
But you should not let anyone else trigger that event (make the TriggerClosed private/protected)

Try this method. This assumes MyClass.Close() raises the MyClass.Closed event.
public void ClosedEventHandlerIsNotCalledAfterBeingRemoved()
{
MyLearningEvent Target = new MyLearningEvent();
EventHandler Target_Closed = new EventHandler((sender, e) => { Assert.Fail("Closed EventHandler was raised after being removed."); });
Target.Closed += Target_Closed;
Target.Closed -= Target_Closed;
Target.OnClosed();
}

Related

How to Convert RoutedEventHandler to EventHandler

I got this situation where I need to create a wrapper around a WPF window that exposes basic features, such as exposing Loaded and Closed events. (There are other wrapper implementations for other UI platforms)
// This works.
public event EventHandler? Closed
{
add => Ref.Closed += value;
remove => Ref.Closed -= value;
}
// This doesn't work.
public event EventHandler? Loaded
{
add => Ref.Loaded += value;
remove => Ref.Loaded -= value;
}
The problem here is that Loaded is a RoutedEventHandled (whereas Closing isn't). Settings an EventHandler doesn't work.
How can I solve this?
Edit: the only solution I can think of is to create a Dictionary of eventhandler wrappers when I add, so that I can get the same reference in remove. Any prettier solution?
Subscribe to the Loaded event of Ref and raise your own custom event when it's raised:
public event EventHandler Loaded;
...
Ref.Loaded += (ss, ee) => Loaded?.Invoke(this, EventArgs.Empty);
I ended up doing this.
public event EventHandler? Loaded
{
add
{
if (value != null)
{
var handler = new RoutedEventHandler((s, e) => value.Invoke(s, e));
_loadedHandlers.Add(value, handler);
Ref.Loaded += handler;
}
}
remove
{
if (value != null)
{
Ref.Loaded += _loadedHandlers[value];
_loadedHandlers.Remove(value);
}
}
}
private Dictionary<EventHandler, RoutedEventHandler> _loadedHandlers = new();

EventHandler raise Event properly

I'm trying to better understand how Events and their handler work, but I don't understand why when raising an event it is usually preferred to raise an identical event, that our event itself.
To be more specific, when looking at msdn doc (https://msdn.microsoft.com/en-us/library/db0etb8x.aspx) it looks like that :
class Counter
{
private int threshold;
private int total;
public Counter(int passedThreshold)
{
threshold = passedThreshold;
}
public void Add(int x)
{
total += x;
if (total >= threshold)
{
ThresholdReachedEventArgs args = new ThresholdReachedEventArgs();
args.Threshold = threshold;
args.TimeReached = DateTime.Now;
OnThresholdReached(args);
}
}
protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
{
EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;
if (handler != null)
{
handler(this, e);
}
}
public event EventHandler<ThresholdReachedEventArgs> ThresholdReached;
}
What I don't understand is why "handler" is created in the OnThresholdReached function, instead of having
protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
{
if (ThresholdReached!= null)
{
ThresholdReached(this, e);
}
}
Why should we create this "handler" ?
Consider this code:
if (ThresholdReached!= null)
{
ThresholdReached(this, e);
}
What would happen in multi-threaded code if the handler for ThresholdReached is removed after if (ThresholdReached!= null), but before ThresholdReached(this, e); is called?
Taking a copy of the handler prevents this situation from occuring and makes the raising of the event thread-safe.

C# Inter class communication with extreme performance

Suppose I want to publish an event from the MarketDataProvider class. The problem is that the event logic resides 2 level deeper.MarketDataProvider --> Level1SocketClient --> Level1MessageHandler.
In short, I would like to raise the event from Level1MessageHandler that MarketDataProvider can publish. The performance here is critical because there are a lot of events generated. I would like to find a clean way of doing it without chaining events from each level.
Rather than having an Event itself, could the intermediate class just pass the Add and Remove calls on to the lowest level class? I.e.
public class Level1MessageHandler
{
public event EventHandler<MessageEventArgs> MessageReceived;
}
public class Level1SocketClient
{
Level1MessageHandler level1Handler;
public event EventHandler<MessageEventArgs> MessageReceived
{
add
{
level1Handler.MessageReceived += value;
}
remove
{
level1Handler.MessageReceived -= value;
}
}
}
This would at least cut out one level of delegate call.
(Or did I get the direction of invocation reversed? Anyway I think the idea is clear.)
Update
An interesting question arises: what happens if the intermediate listener needs to be disposable, and when disposed, remove all the events added through it? You can do it by recording the events added in a local event, like so:
public interface IMessagePublisher<TEventArgs> where TEventArgs : EventArgs
{
event EventHandler<TEventArgs> MessageReceived;
}
public class MessageRePublisher<TEventArgs> : IMessagePublisher<TEventArgs>, IDisposable where TEventArgs : EventArgs
{
readonly IMessagePublisher<TEventArgs> publisher;
public MessageRePublisher(IMessagePublisher<TEventArgs> publisher)
{
this.publisher = publisher;
}
EventHandler<TEventArgs> messageReceivedEventsAdded = null;
public event EventHandler<TEventArgs> MessageReceived
{
[MethodImpl(MethodImplOptions.Synchronized)]
add
{
// events are multicast delegates, which are immutable. We need to remove the previous
// combined event, create a new combined event, then added that.
// More here: http://msdn.microsoft.com/en-us/magazine/cc163533.aspx
if (messageReceivedEventsAdded != null)
publisher.MessageReceived -= messageReceivedEventsAdded;
messageReceivedEventsAdded += value;
if (messageReceivedEventsAdded != null)
publisher.MessageReceived += messageReceivedEventsAdded;
}
[MethodImpl(MethodImplOptions.Synchronized)]
remove
{
if (messageReceivedEventsAdded != null)
publisher.MessageReceived -= messageReceivedEventsAdded;
messageReceivedEventsAdded -= value;
if (messageReceivedEventsAdded != null)
publisher.MessageReceived += messageReceivedEventsAdded;
}
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (messageReceivedEventsAdded != null && publisher != null)
{
publisher.MessageReceived -= messageReceivedEventsAdded;
}
}
messageReceivedEventsAdded = null;
}
#endregion
}
The intermediate listener combines all its events into a single concatenated event, then adds and removes that every time.

c# check if event is null

I have this event in a webservice:
public event FindProductsByCharacteristicsCompletedEventHandler FindProductsByCharacteristicsCompleted
{
[MethodImpl(MethodImplOptions.Synchronized)]
add
{
_findProductsByCharacteristicsCompleted += value;
}
[MethodImpl(MethodImplOptions.Synchronized)]
remove
{
_findProductsByCharacteristicsCompleted -= value;
}
}
And im then checking if the event value is null with this later in the class:
private void OnFindProductsByCharacteristicsOperationCompleted(object arg)
{
var handler = _findProductsByCharacteristicsCompleted;
if (handler == null)
return;
handler(this, new FindProductsByCharacteristicsCompletedEventArgs(completedEventArgs.Results, completedEventArgs.Error, completedEventArgs.Cancelled, completedEventArgs.UserState));
}
Your event implementation looks like it is an endless recursion. You are using the property itself in its implementation.
Change it to this:
private FindProductsByCharacteristicsCompletedEventHandler
_findProductsByCharacteristicsCompleted;
public event FindProductsByCharacteristicsCompletedEventHandler
FindProductsByCharacteristicsCompleted
{
[MethodImpl(MethodImplOptions.Synchronized)]
add
{
_findProductsByCharacteristicsCompleted += value;
}
[MethodImpl(MethodImplOptions.Synchronized)]
remove
{
_findProductsByCharacteristicsCompleted -= value;
}
}
And now, implement your method like this:
var handler = _findProductsByCharacteristicsCompleted;
if(handler == null)
return;
handler(this, new FindProductsByCharacteristicsCompletedEventArgs(...));
This has the advantage that it is thread-safe.
Even if someone detached the last handler from the event after you checked for null but before you actually raised the event, you would not get an exception, because you are operating on the unchanged local variable.

How to write a Trigger?

I want my C# code to call an event whenever a value is assigned to my object.
How exactly would I need to go about that?
class MyClass {
ManualResetEvent mre;
public MyClass() {
mre = new ManualResetEvent(false);
Data = null;
}
public object Data { get; set; }
void DataSet(object sender, EventArgs e) {
Console.WriteLine("object Data has been set.");
mre.Set();
}
}
Delegates don't seem to be what I need. An event, maybe? How would I write such an event, if so?
MyClass mc;
void processA() {
mc = new MyClass();
mc.Data = GetDataFromLongProcess();
}
private object data;
public object Data {
get { return data;}
set {
if(value != data) {
data = value;
OnDataChanged();
}
}
}
protected virtual void OnDataChanged() {
EventHandler handler = DataChanged;
if(handler != null) handler(this, EventArgs.Empty);
}
public event EventHandler DataChanged;
then hook any code to the DataChanged event. For example:
MyClass mc = ...
mc.DataChanged += delegate {
Console.WriteLine("new data! wow!");
};
If you want to fire an event when your property is set, you would do something like this:
public event Action OnDataChanged;
protected object _data = null;
public object Data
{
get { return _data; }
set
{
_data = value;
if(OnDataChanged != null)
OnDataChanged();
}
}
Then you would simply wire up event handlers to your object like so:
mc = new MyClass();
mc.OnDataChanged += delegate() { Console.WriteLine("It changed!"); };
mc.Data = SomeValue();
I think you're on the right track with an event-based model. Also take a look at the Observer pattern (which is the basis for .Net delegates and events underneath it all, as I understand):
http://www.dofactory.com/Patterns/PatternObserver.aspx
But the bottom line, as the other useful answer so far (Mr. Gravell's implementation) indicates, you're going to have to have code IN the setter to get it hooked up. The only alternative would be to poll the value for changes, which just smells bad to me.
you could implement INotifyPropertyChanged (this is more or less a event) or you could take your class a Action (Trigger) and call this, whenn the property changed.
Just don't use automatic properties but a concrete setter and call your event/trigger from there.
Conceptually, you would define an event in your class, and in your property set blocks, you would invoke the event with the necessary arguments to determine what just happened.
public event SomeDelegateThatTakesIntAsParameter myEvent;
void SetData(int data)
{
if(myEvent!= null)
myEvent(data)
}

Categories

Resources