Dear all,
I plan to rewrite a Java library to C#. This library makes heavy use of custom event handling, i. e. it contains lot of classes XYZ that are in fact Observable, XYZChangeEvent, and interface XYZChangeListener that are implemented by Observers. Frequently, an Observable is an Observer at the same time, and propagates change events that it has received from its Oberservables to its own Observers.
This event handling will be implemented using the C# styl way, i. e. by using events instead of interfaces to couple the Observers and Observables.
I have read various threads in this forum (such as http://www.csharpforums.net/showthread.php/3628-understanding-Delegates-and-Events ) and others, and I think that I have grasped the basic concepts. However, I still feel a bit unsure about some implementation details.
Here is a set of classes that I gave written as prototypes to learn the various options:
Some questions:
Obviously, I do not need any interfaces that declare a by definition public method. An observer just needs a method with a suitable signature. In the two event subscriber classes above, the respective event handler methods are public. However, this would not be necessary for the ItemChangeListenerWithRef instance. An ItemChangeListenerWithRef instance only subscribes to event of those items to which it has reference, and is never used as a subscriber by an external class. It would thus be possible to make the ItemChanged method protected or even private. Is such an approach "allowed", or should such an approach be avoided?
The OnItemChanged method of the Item class gets a string parameter. I have read that the event raising method such be declared to have a single parameter that derives from EventArgs. Is this just a recommendation more like a requirement? The benefit of the OnItemChanged(string) method is that it is shorter, since the EventArgs instance does only need to be created in a single place. In a real world, the Item class will have more than just one or a few properties that could be changed, and whose change will have to raise a ChangeEvent.
I have also read the recommendation that I should forget about custom events, and just the interface INotifyPropertyChanged to implement an event notification mechanism. However, this approach only allows to transfer the sender (as object) of the event and the name of the changed property to the subscribers. Using a custom EventArgs offers far more options to to carry additional informations. Is the use of custom EventArgs still considered good practice? We are not talking about a Gui framework.
Finally, is the naming used for the events, the event raising methods, and for the observers ok?
Thanks for any feedback!
I plan to rewrite a Java library to C#. This library makes heavy use of custom event handling, i. e. it contains lot of classes XYZ that are in fact Observable, XYZChangeEvent, and interface XYZChangeListener that are implemented by Observers. Frequently, an Observable is an Observer at the same time, and propagates change events that it has received from its Oberservables to its own Observers.
This event handling will be implemented using the C# styl way, i. e. by using events instead of interfaces to couple the Observers and Observables.
I have read various threads in this forum (such as http://www.csharpforums.net/showthread.php/3628-understanding-Delegates-and-Events ) and others, and I think that I have grasped the basic concepts. However, I still feel a bit unsure about some implementation details.
Here is a set of classes that I gave written as prototypes to learn the various options:
C#:
namespace EventStuff
{
public static class EventHelper
{
public static void Raise<T>(this EventHandler<T> handler, Object sender, T e) where T: EventArgs{
if(handler != null){
handler(sender,e);
}
}
}
public class ItemChangeEvent: EventArgs
{
private Item source;
private string message;
public ItemChangeEvent(Item source, string message)
{
this.source = source;
this.message = message;
}
public Item Source{
get{return source;}
}
public string Message{
get{return message;}
}
}
public class Item
{
public event EventHandler<ItemChangeEvent> ItemChanged;
private string label;
public Item(string label)
{
this.label = label;
}
public string Label{
get{return this.label;}
set{
this.label = value;
OnItemChanged("Label changed");
this.label = value;
}
}
public void OnItemChanged(string message){
ItemChanged.Raise(this, new ItemChangeEvent(this,message));
}
}
public class ItemChangeListenerWithRef
{
private string name;
private Item item;
public ItemChangeListenerWithRef(string name, Item item)
{
this.name = name;
this.item = item;
item.ItemChanged+=this.ItemChanged;
}
public void ItemChanged(Object sender, ItemChangeEvent e){
Console.WriteLine("I am '" + name + "' with an item reference. Change detected for item " +e.Source + " with message '" + e.Message+"'");
}
}
public class ItemChangeListenerExcludingRef
{
private string name;
public ItemChangeListenerExcludingRef(string name)
{
this.name = name;
}
public void ItemChanged(Object sender, ItemChangeEvent e){
Console.WriteLine("I am '" + name + "'without an item reference. Change detected for item " +e.Source + " with message '" + e.Message+"'");
}
}
public class ItemEventTest
{
public static void Main(string[] args)
{
Item first = new Item("My first item");
ItemChangeListenerExcludingRef noRef = new ItemChangeListenerExcludingRef("First logger no ref");
first.addItemChangeListener(noRef);
ItemChangeListenerWithRef withRef = new ItemChangeListenerWithRef("First logger with ref", first);
first.Listeners += new Item.Listener(noRef.itemChanged);
first.Label = "My first changed item";
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}
Obviously, I do not need any interfaces that declare a by definition public method. An observer just needs a method with a suitable signature. In the two event subscriber classes above, the respective event handler methods are public. However, this would not be necessary for the ItemChangeListenerWithRef instance. An ItemChangeListenerWithRef instance only subscribes to event of those items to which it has reference, and is never used as a subscriber by an external class. It would thus be possible to make the ItemChanged method protected or even private. Is such an approach "allowed", or should such an approach be avoided?
The OnItemChanged method of the Item class gets a string parameter. I have read that the event raising method such be declared to have a single parameter that derives from EventArgs. Is this just a recommendation more like a requirement? The benefit of the OnItemChanged(string) method is that it is shorter, since the EventArgs instance does only need to be created in a single place. In a real world, the Item class will have more than just one or a few properties that could be changed, and whose change will have to raise a ChangeEvent.
I have also read the recommendation that I should forget about custom events, and just the interface INotifyPropertyChanged to implement an event notification mechanism. However, this approach only allows to transfer the sender (as object) of the event and the name of the changed property to the subscribers. Using a custom EventArgs offers far more options to to carry additional informations. Is the use of custom EventArgs still considered good practice? We are not talking about a Gui framework.
Finally, is the naming used for the events, the event raising methods, and for the observers ok?
Thanks for any feedback!