Implementing an event inherited from an interface - c#

In my project, I need to implement an event that fires when a popup or something similar is pulled up so that I can close anything that needs to hide behind it for whatever reason.
For context, I have 3 files in play here, MainShell which fires the event, IShell which is an interface that MainShell implements and defines the event, and Reports which listens for the event. I could have put the event in MainShell and made everything simpler, however the project references would become circular if I did that. That's just what I have to work with. I can, however, refer to the IShell interface that defines the functions MainShell uses. Unfortunately, it seems attempting to use an event from a derived class/interface causes the implementation to become very complicated and picky for some reason.
In my interface file:
public class ModuleShownEventArgs : EventArgs { }
public delegate void ModuleShownEventHandler(object sender, ModuleShownEventArgs e);
public interface IShell {
event ModuleShownEventHandler ModuleShown;
... }
In my listening class:
public Reports() {
...
Container.Shell.ModuleShown += Shell_ModuleShown;
... }
private void Shell_ModuleShown(object sender, ModuleShownEventArgs e) {}
In my event firing class:
event ModuleShownEventHandler IShell.ModuleShown
{
add
{
((IShell)this).ModuleShown += value;
}
remove
{
((IShell)this).ModuleShown -= value;
}
}
public void OnModuleShown()
{
ModuleShownEventHandler handler = ((IShell)this).ModuleShown;
if (handler != null)
handler(this, new ModuleShownEventArgs());
}
I've managed to stop most of the compiler's complaints, but I'm down to one problem: there's an error where I assign handler = ModuleShown,
the event 'IShell.ModuleShown' can only appear on the left hand side
of += or -=
This prevents me from easily comparing my event to null for checking, and prevents me from firing my event at all.
Questions
How can I get this to work? Why can't I fire my event? Why does defining events change so drastically when they come from a base class/interface? Keep in mind that this project is quite large and I've only started working on it recently, so I can't make sweeping structural changes to it.
I am using Visual Studio 2013, and my project's .NET Framework version is 4.0.

The issue is that you are using explicit interface implementation. You should be using implicit instead.
public class Shell : IShell
{
public event ModuleShownEventHandler ModuleShown;
public void OnModuleShown()
{
ModuleShownEventHandler handler = ModuleShown;
if (handler != null)
{
handler(this, new ModuleShownEventArgs());
}
}
}
https://msdn.microsoft.com/en-us/library/ms173157.aspx
Ideally you will be passing around the instance that implements IShell as the interface if your concern was to hide the event from the Shell implementation. Typically, you use explicit interface implementations when you do not want your class to publicly expose an interface specific member.
I hope this helps.

It should look something like this instead.
public void OnModuleShown()
{
if (((IShell)this).ModuleShown != null);
(((IShell)this).ModuleShown)(this, new ModuleShownEventArgs());
}

Related

Why the method that fires the C# event must be protected virtual? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
While reading a book on C# I found this source code :
public class Stock
{
...
public event EventHandler<PriceChangedEventArgs> PriceChanged;
protected virtual void OnPriceChanged (PriceChangedEventArgs e)
{
if (PriceChanged != null) PriceChanged (this, e);
}
}
The author states that the standard event pattern requires, I quote :
The pattern requires that you write a protected virtual method that fires the event. The name must match the name of the event, prefixed with the word On, and then accept a single EventArgs argument:
Why should it be protected and virtual ?
It's a pattern from the days of "Component-oriented programming" - it's still valid, but
not as relevant today as Delegate-based events which use the OnEventName-pattern aren't as popular because UI programming is either done in JavaScript (thus avoiding .NET entirely) or uses the ViewModel-pattern which doesn't use Delegate events at all.
As an explanation for "why" - let's look at the canonical example of Component-oriented programming: WinForms controls. All controls derive from System.Windows.Forms.Control which represents an ecapsulation of a Win32 "hWnd" window, which is a 2D surface which accepts Win32 Window Messages for user-input (mouse, keyboard, touch, etc) and paints to itself.
The Control class exposes its own initial set of events, like Load and MouseMove. All of these events are exposed in two ways:
Publicly accessible event members. Essentially multicast, strongly-typed Delegate properties.
These are subscribe-only. So a consumer of a component can listen to events, but they cannot invoke events themselves.
In C# they look like this:
public event DelegateType EventName;
For example:
public class Control : Component
{
public event EventHandler Click;
}
Methods that invoke each event (by invoking the multicast Delegate).
These methods are not public because that would break encapsulation (i.e. you don't want a consumer to be able to raise events), so they can be either private or protected.
By choosing protected instead of private means that subclasses can invoke events themselves, if appropriate.
In C# they look like this:
public class Control : Component
{
public event EventHandler Click;
protected virtual void OnClick(EventArgs e)
{
this.Click?.Invoke( this, e );
}
private void OnWin32WindowMessage( Message m )
{
switch( m.EventId )
{
case Win32.MouseClick:
this.OnClick( EventArgs.Empty );
break;
case Win32.MouseMove:
this.OnMouseMove( EventArgs.Empty );
break;
case Win32.KeyDown:
this.OnKeyDown( EventArgs.Empty );
break;
// etc
}
}
}
You can argue that if a component subclass only wants to subscribe to events belonging to its superclass then it should not be able to invoke certain events themselves and so the On{EventName} methods should be private and not protected - and the subclass should set-up an EventHandler inside its constructor. Like so:
public class MySubclass : Control
{
public MySubclass()
{
this.Click += new EventHandler( this.Clicked );
}
private void Clicked(Object sender, EventArgs e)
{
MessageBox.Show( "boop!" );
}
}
...and this is valid.
However, there are at least three reasons for using protected virtual methods instead of private:
The advantage to using virtual methods is that it lets the subclass override the behaviour.
For example, if the superclass has a trivial OnClick method that simply (and always) invokes the Click event but you want your subclass to only allow the Click event to be invoked if this.Disabled == true):
public class MySubclass : Control
{
protected override OnClick( EventArgs e )
{
if( !this.Disabled )
{
base.OnClick( e );
}
}
public Boolean Disabled { get; set; }
}
Allowing subclasses to be notified first.
Multicast delegates in C# do not offer any control over the precise order-of-execution - by using virtual methods this allows a subclass to always be notified first, before any external consumers. This is important if the state of MySubclass will change in an event-handler. For example:
public class MySubclass : Control
{
public MySubclass()
{
this.Click += new EventHandler( this.Clicked );
}
private void Clicked(Object sender, EventArgs e)
{
this.BackgroundColor = Colors.Red;
}
}
public class MyForm : Form
{
private readonly MySubclass sc;
public MyForm()
{
this.sc = new MySubclass();
this.Controls.Add( this.sc );
this.sc.Click += new EventHandler( this.SCClicked );
}
private void SCClicked (Object sender, EventArgs e)
{
MessageBox.Show( "The control's colour is " + this.sc.BackgroundColor );
}
}
As it's possible for MyForm.SCClicked to run before MySubclass.Clicked, SCClicked may report the old colour, not the new colour.
By using a virtual method override this can be avoided:
public class MySubclass : Control
{
protected override void OnClick(EventArgs e)
{
this.BackgroundColor = Colors.Red;
base.OnClick( e );
}
}
public class MyForm : Form { /* unchanged */ }
...and it will now work as-expected.
The other reason is performance.
Delegates are more expensive than a virtual method call. So by overriding the method means a subclass can subscribe to an event with less runtime overhead than using an event-handler.
While this isn't important for one-off events like Load or maybe even Paint and Click, it can matter if it's a high-frequency event (think: thousands of times per second).
Performance can matter, even on today's computers that are 10-50x faster than the late-1990s machines that were around when .NET and WinForms was originally designed. Especially as event-handling code in WinForms has to run in the UI thread.
Today, high-frequency events tend to use the Observer pattern instead of Delegate events, precisely because that avoids the overhead of using delegates (the linked Wikipedia article does describe C#'s event support as an example of the Observer pattern, which is strictly true - but when people talk about the Observer pattern they usually mean something like Reactive programming: http://reactivex.io/
virtual means that a class can inherit from Stock and override that method.
protected means that only Stock or classes that inherit from Stock can access that method.
Events by themselves don't have to be fired from virtual or protected methods. This is just a pattern that some applications use, which allow derived classes to fire the event as well.
Classes that inherit from Stock and override OnPriceChanged can call base. OnPriceChanged and It would fire the event.
For example,
class MyStock : Stock
{
protected override void OnPriceChanged (PriceChangedEventArgs e)
{
// Do something
base.OnPriceChanged(e); // will call OnPriceChanged in the base class, and fire the event
}
}

Calling event of another class

I am new to C# and programming in general and am trying to figure out how to use events. Previously I have been programming with ActionScript3, and there events are a special class that you inherit from if you want to create your own events, and then that event can be called by any other class.
With C# I have tried to do something similar, like so:
public class EventManager
{
public delegate void TempDelegate();
public static event TempDelegate eSomeEvent;
}
public class SomeOtherClass
{
//doing some stuff, then:
if (EventManager.eSomeEvent != null)
{
EventManager.eSomeEvent();
}
}
This gives me a compiler error CS0070: The event 'EventManager.eSomeEvent' can only appear on the left hand side of += or -= (except when used from within the type 'EventManager')
The information about this error over on the msdn indicates that I should use += instead of trying to call the event, but I don't really understand this. I'm not trying to subscribe anything from SomeOtherClass to the event delegate, I am just trying to call this event so that it starts executing those functions that are already subscribed to that event.
So is it possible to do it this way? If not, is it at all possible to call an event that is of one class, from another class? I simply wish to reuse certain events in my classes rather than creating many similar ones in multiple classes.
Any advice with this would be greatly appreciated!
You can wrap the event call in a public method and use that from your other classes.
public void OnSomeEvent()
{
var handler = eSomeEvent;
if (handler != null) handler(this, null);
}
However you might want to look at the design again, if you are really sure the event should be on a different class than the one triggering it.
Well, the typical solution is to put eSomeEvent invocation into the EventManager class
public class EventManager
{
public delegate void TempDelegate();
public static event TempDelegate eSomeEvent;
// Not thread safe as well as your code
// May be internal, not public is better (if SomeOtherClass is in the same namespace)
public static void PerformSomeEvent() {
if (!Object.ReferenceEquals(null, eSomeEvent))
eSomeEvent(); // <- You can do it here
}
}
public class SomeOtherClass
{
//doing some stuff, then:
EventManager.PerformSomeEvent();
}

Public event of base class in derived class

I have a base-class (let it be SomeBaseClass) containing a public event (SomeEvent) and I have a derived-class in which I want to raise this event but I can't(!!) VS 2010 says me (in derived-class in line: base.SomeEvent != null) "The event 'SomeBaseClass.SomeEvent' can only appear on the left hand side of += or -=". If I replace base on this It is make no sense.
No, it's absolutely right - the event is only an event (with subscription and unsubscription) as far as a derived class is concerned. If your base class wants to let derived classes raise the event, it should include a protected method to do so (typically a virtual OnFoo(EventHandler) for an event called Foo with the EventHandler type, for example). Note that if you write a field-like event in C# like this:
public event EventHandler Foo;
That's actually declaring a private field called Foo (which that class and any nested classes have access to) and a public event (which consists only of subscribe/unsubscribe). You could declare your own "custom" event like this:
protected EventHandler foo;
// Note: not thread-safe. Only present for demonstration purposes.
public event EventHandler Foo
{
add { foo += value; }
remove { foo -= value; }
}
and then derived classes would have access to the field... but I wouldn't recommend that. (I rarely declare non-private fields, other than for constants.)
You need to do it the right way (i.e., the idiomatic way in C#)
public class Base {
public event EventHandler<EventArgs> SomeEvent;
protected virtual void OnSomeEvent(EventArgs e) {
EventHandler<EventArgs> handler = SomeEvent;
if (handler != null) {
handler(this, e);
}
}
}
public class Derived {
protected virtual void OnSomeEvent(EventArgs e) {
// derived event handling here
// then invoke the base handler
base.OnSomeEvent(e);
}
}
The reason that you do it like this is because events can only be invoked from within the defining class.

How do I subscribe to PropertyChanged event in my ViewModel?

I have core functionality encapsulated in ViewModelBase
Now I want to see when PropertyChanged event was raised by ViewModelBase and act on it. For example, when one property was changed on ViewModelBase - I want to change property on my ViewModel
How do I achieve this?
public class MaintainGroupViewModel : BaseViewModel<MEMGroup>
{
public abstract class BaseViewModel<T> : NotificationObject, INavigationAware
where T : Entity
{
Usually I use register to the PropertyChanged event in the class Constructor
public MyViewModel()
{
this.PropertyChanged += MyViewModel_PropertyChanged;
}
and my PropertyChanged event handler looks like this:
void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "SomeProperty":
// Do something
break;
}
}
I am concerned that you're effectively doing a 'manual binding' (bad) for a property in a derived class to a value on the base class (also bad). The whole point of using inheritance is that the derived class can access things in the base class. Use a protected modifier to indicate things should only be accessible to derived classes.
I would suggest this (potentially) more correct method:
Base class:
protected virtual void OnMyValueChanged() { }
Derived class:
protected override void OnMyValueChanged() { /* respond here */ }
Really, subscribing to an event in the base class of the very class you're writing just seems incredibly backwards - what's the point of using inheritance over composition if you're going to compose yourself around yourself? You're literally asking an object to tell itself when something happens. A method call is what you should use for that.
In terms of "when one property was changed on ViewModelBase - I want to change property on my ViewModel", ... they are the same object!
The direct way to subscribe to property changes is using INotifyPropertyChanged if your BaseViewModel implements it:
PropertyChanged += (obj, args) =>
{ System.Console.WriteLine("Property " + args.PropertyName + " changed"); }
If it doesn't, then it has to be a DependencyObject, and your properties have to be DependencyProperties (which is probably a more complicated way).
This article describes how to subscribe for DependencyProperty changes.

Why events can't be used in the same way in derived classes as in the base class in C#?

In following code, I want to extend the behaviour of a class by deriving/subclassing it, and make use of an event of the base class:
public class A
{
public event EventHandler SomeEvent;
public void someMethod()
{
if(SomeEvent != null) SomeEvent(this, someArgs);
}
}
public class B : A
{
public void someOtherMethod()
{
if(SomeEvent != null) SomeEvent(this, someArgs); // << why is this not possible?
//Error: The event 'SomeEvent' can only appear on the left hand side of += or -=
//(except when used from within the type 'A')
}
}
Why isn't it possible?
And what is the common solution for this kind of situation?
Others have explained how to get round the issue, but not why it's coming up.
When you declare a public field-like event, the compiler creates a public event, and a private field. Within the same class (or nested classes) you can get at the field directly, e.g. to invoke all the handlers. From other classes, you only see the event, which only allows subscription and unsubscription.
The standard practice here is to have a protected virtual method OnSomeEvent on your base class, then call that method in derived classes. Also, for threading reasons you will want to keep a reference to the handler before checking null and calling it.
For an explanation of the why read Jon Skeet's answer or the C# specification which describes how the compiler automatically creates a private field.
Here is one possible work around.
public class A
{
public event EventHandler SomeEvent;
public void someMethod()
{
OnSomeEvent();
}
protected void OnSomeEvent()
{
EventHandler handler = SomeEvent;
if(handler != null)
handler(this, someArgs);
}
}
public class B : A
{
public void someOtherMethod()
{
OnSomeEvent();
}
}
Edit: Updated code based upon Framework Design Guidelines section 5.4 and reminders by others.
Todd's answer is correct. Often you will see this implemented throughout the .NET framework as OnXXX(EventArgs) methods:
public class Foo
{
public event EventHandler Click;
protected virtual void OnClick(EventArgs e)
{
var click = Click;
if (click != null)
click(this, e);
}
}
I strongly encourage you to consider the EventArgs<T>/EventHandler<T> pattern before you find yourself making all manner of CustomEventArgs/CustomEventHandler for raising events.
The reason the original code doesn't work is because you need to have access to the event's delegate in order to raise it, and C# keeps this delegate private.
Events in C# are represented publicly by a pair of methods, add_SomeEvent and remove_SomeEvent, which is why you can subscribe to an event from outside the class, but not raise it.
My answer would be that you shouldn't have to do this.
C# nicely enforces Only the type declaring/publishing the event should fire/raise it.
If the base class trusted derivations to have the capability to raise its events, the creator would expose protected methods to do that. If they don't exist, its a good hint that you probably shouldn't do this.
My contrived example as to how different the world would be if derived types were allowed to raise events in their ancestors. Note: this is not valid C# code.. (yet..)
public class GoodVigilante
{
public event EventHandler LaunchMissiles;
public void Evaluate()
{
Action a = DetermineCourseOfAction(); // method that evaluates every possible
// non-violent solution before resorting to 'Unleashing the fury'
if (null != a)
{ a.Do(); }
else
{ if (null != LaunchMissiles) LaunchMissiles(this, EventArgs.Empty); }
}
virtual protected string WhatsTheTime()
{ return DateTime.Now.ToString(); }
....
}
public class TriggerHappy : GoodVigilante
{
protected override string WhatsTheTime()
{
if (null != LaunchMissiles) LaunchMissiles(this, EventArgs.Empty);
}
}
// client code
GoodVigilante a = new GoodVigilante();
a.LaunchMissiles += new EventHandler(FireAway);
GoodVigilante b = new TriggerHappy(); // rogue/imposter
b.LaunchMissiles += new EventHandler(FireAway);
private void FireAway(object sender, EventArgs e)
{
// nuke 'em
}
Wrap it with a protected virtual On... method:
public class BaseClass
{
public event EventHandler<MyArgs> SomeEvent;
protected virtual void OnSomeEvent()
{
if(SomeEvent!= null)
SomeEvent(this, new MyArgs(...) );
}
}
Then override this in a derived class
public class DerivedClass : BaseClass
{
protected override void OnSomeEvent()
{
//do something
base.OnSomeEvent();
}
}
You'll set this pattern all over .Net - all form and web controls follow it.
Do not use the prefix Raise... - this is not consistent with MS's standards and can cause confusion elsewhere.

Categories

Resources