Here are 3 C# classes :
class StartClass
{
event StartEvent;
// some code
class MidClass
{
private StartClass _startClass;
public MidClass (StartClass startClass)
{
_startClass = startClass;
}
// some code
class EndClass
{
private MidClass _midClass;
public EndClass (MidClass midClass)
{
_midClass = midClass;
}
// some code
public void OnStartEvent ()
{
// code to be executed on StartEvent called
}
What's best way if you want to attach EndClass.OnStartEvent
listener to StartClass.StartEvent
event ?
I think the best way would be to create a MidClass.StartEvent
property referencing StartClass.StartEvent
event in order to be able to attach the listener in EndClass
doing _midClass.StartEvent = OnStartEvent;
. Am I right ? How to attach StartClass.StartEvent
to MidClass.StartEvent
?
CodePudding user response:
In C# an event is much like a property. It is a wrapper for a delegate. Usually we are using auto-implemented events. But we can expand them. Properties have get
and set
accessors. Events have add
and remove
accessors.
class MidClass
{
private readonly StartClass _startClass;
public MidClass (StartClass startClass)
{
_startClass = startClass;
}
public event EventHandler StartEvent
{
add => _startClass.StartEvent = value;
remove => _startClass.StartEvent -= value;
}
}
Here, we create a StartEvent
in MidClass
that is a wrapper for the corresponding event in StartClass
. StartClass.StartEvent
must be public.
The advantage of this approach is that an event handler subscribing to MidClass.StartEvent
will directly be attached to StartClass.StartEvent
, with no intermediate call occurring when the event is risen.
One word to naming. Methods named OnEventName
are usually used to raise events, while methods named PublisherName_EventName
are used for event handlers.
class StartClass
{
public event EventHandler StartEvent;
private virtual void OnStartEvent()
{
StartEvent?Invoke(this, EventArgs.Empty);
}
}
class EndClass
{
private MidClass _midClass;
public EndClass (MidClass midClass)
{
_midClass = midClass;
_midClass.StartEvent = MidClass_StartEvent;
}
private void MidClass_StartEvent (object sender, EventArgs e)
{
// Code to be executed when StartEvent is triggered
}
}
CodePudding user response:
I think the best way would be to create a
MidClass.StartEvent
property referencingStartClass.StartEvent
event in order to be able to attach the listener inEndClass
doing_midClass.StartEvent = OnStartEvent
;. Am I right?
If you want to keep the reference to StartClass
a private implementation detail of MidClass
: Yes, implementing a "proxy" StartEvent
in MidClass is the right way to do it.
How to attach StartClass.StartEvent to MidClass.StartEvent ?
By attaching a listener to _startClass.StartEvent
which just raises the corresponding event in MidClass
:
class MidClass
{
public event EventHandler StartEvent;
private readonly StartClass _startClass;
public MidClass(StartClass startClass)
{
_startClass = startClass;
_startClass.StartEvent = (sender, e) => this.StartEvent?.Invoke(this, e);
}
...
}
Note that I also added the readonly
modifier to _startClass
: If the value of _startClass
changes during the lifetime of MidClass
, you need to detach your event handler from the old reference and attach it to the new reference.