I'm implementing a menu system that uses a composite design pattern. I have the following MenuElement interface:
public interface MenuElement
{
void AddMenuElement( MenuElement menuToAdd );
void RemoveMenuElement( MenuElement menuToRemove );
MenuElement GetMenuElement( int index );
void Activate();
}
I was thinking of including an "OnActivate" event in this interface so that MenuItems that implement this interface can trigger functions when activated. I tried implementing it like this:
public interface MenuElement
{
public delegate void MenuEvent();
event MenuEvent onActivate;
void AddMenuElement( MenuElement menuToAdd );
void RemoveMenuElement( MenuElement menuToRemove );
MenuElement GetMenuElement( int index );
void Activate();
}
However, the compiler won't let me declare a delegate inside an interface. I'm aware of a C# event type called EventHandler but unlike my desired MenuEvent, it requires both object and EventArgs parameters. I've also considered moving my event and delegate over to MenuItem instead, but I'm still curious if it is possible to have an interface include a custom event.
Is this possible? Or would I have to use C#'s EventHandler class in this situation?
Why don't you use EventHandler
? E.g.
// I've added "I" since it's an Interface
public interface IMenuElement {
void AddMenuElement(MenuElement menuToAdd);
void RemoveMenuElement(MenuElement menuToRemove);
void Activate();
// I've changed your
// MenuElement GetMenuElement(int index)
// to indexer
MenuElement this[int index] {get;}
// Event of interest; I've renamed it from onActivate
event EventHandler Activated;
}
...
// Possible interface implementation
public class MyMenuElement: IMenuElement {
...
// name like "onActivate" is better to use here, as a private context
private void onActivated() {
if (Object.ReferenceEquals(null, Activated))
return;
Activated(this, EventArgs.Empty);
}
public void Activate() {
// Some staff here
...
// Raising the event
onActivated();
}
}
An interface is not meant to implement a field; it is there to define contracts (signatures), that is all.
If you want to provide a base field, combined with an "interface", consider an abstract class. abstract classes are useful for providing partial implementations.
public abstract class MenuElement
{
public delegate void MenuEvent();
event MenuEvent onActivate;
abstract virtual void AddMenuElement( MenuElement menuToAdd );
abstract virtual void Activate();
}
If it is important to also have an interface then just have your MenuElement class inherit the interface, and pass it on to its descendants. Abstract classes can inherit interfaces without implementing them, in order to pass them along to the leaf classes, maintaining the convenience factor.
Keep in mind you can also declare a property in an interface, but leaf classes still have to implement the property.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With