I'm currently working on a very cool (top secret) project with 3 Leaf, where I need to
know when my application is online or offline. Sean told me to look into
the System.Net.NetworkInformation namespace, and even got me hooked up
with a solid example of using it that Arian had done for another
up-and-coming project involving Tablet PC.
But I needed to expose the 'notification' to a couple of key areas in my
class, so I figured I'd abstract all of the happy logic down into a single
class that would make for even easier to reuse by providing encapsulation of the notifications as well
as a good way to evaluate current status as needed.
First, you'll need an enum:
public enum ConnectionStatus
{
Unknown,
Connected,
Disconnected
}
Defaulting to Unknown is sensible enough - and hopefully you'll never stay
there long. Once that's done, a simple delegate, that will be used for
notifications/events:
public delegate void NetworkStatusChangedEventHandler(
object sender, NetworkStatusChangedEventArgs e);
Of course, in order for that event to work, we'll need a custom EventArgs
class to match the signature of the event - and, logically, this class can send
the new status along as part of the Event so that anything subscribing to the
Event will be informed immediately of the new state:
public class NetworkStatusChangedEventArgs : EventArgs
{
private ConnectionStatus _state;
public ConnectionStatus ConnectionState
{
get { return _state; }
set { _state = value; }
}
public NetworkStatusChangedEventArgs(ConnectionStatus state)
{
this._state = state;
}
}
The class will effectively just wrap some of the key components of the
namespace, and make them more easy to interact with. In addition to an Event
that announces changes in the network status the class will expose a simple
property that lets us interrogate it directly for the network connectivity
status. So it effectively ends up looking, modelled, like so:
Under the covers, the only non-transparent bit of logic is the need for
synchronization locking, just in case the network adapter gets a bit flaky and doesn't know if it's online/offline. Otherwise it's a simple question of abstracting away an internally broadcast event, and exposing a simple property:
public class NetworkStatus
{
private object _syncLock = new object();
private NetworkAvailabilityChangedEventHandler networkChanged;
public event NetworkStatusChangedEventHandler NetworkStatusChanged;
private ConnectionStatus _status;
public ConnectionStatus ConnectivityStatus
{
get { return _status; }
set { _status = value; }
}
public NetworkStatus()
{
this.DetermineNetworkStatus();
networkChanged = new NetworkAvailabilityChangedEventHandler(
NetworkChange_NetworkAvailabilityChanged);
NetworkChange.NetworkAvailabilityChanged += networkChanged;
}
private void NetworkChange_NetworkAvailabilityChanged(
object sender, NetworkAvailabilityEventArgs e)
{
this.DetermineNetworkStatus();
}
private void DetermineNetworkStatus()
{
bool online = NetworkInterface.GetIsNetworkAvailable();
ConnectionStatus current =
online ? ConnectionStatus.Connected :
ConnectionStatus.Disconnected;
bool changed = false;
lock (this._syncLock)
{
if (this._status != current)
{
this._status = current;
changed = true;
}
}
if (changed)
{
NetworkStatusChangedEventArgs e =
new NetworkStatusChangedEventArgs(current);
this.OnChanged(e);
}
}
protected virtual void OnChanged(NetworkStatusChangedEventArgs e)
{
if (NetworkStatusChanged != null)
NetworkStatusChanged(this, e);
}
}
And voila! a simple to use NetworkStatus class. It can now be bound up as needed, for example, in the constructor of a class that will benefit from it:
private void ClassThatNeedsNetworkNotification_Load(
object sender, EventArgs e)
{
this._networkStatus = new NetworkStatus();
ConnectionStatus status = this._networkStatus.ConnectivityStatus;
this.BindConnectionStatus(status);
this._networkStatus.NetworkStatusChanged
+= new NetworkStatusChangedEventHandler(NetworkStatusChanged);
// other wire up as needed
}
private void NetworkStatusChanged(
object sender, NetworkStatusChangedEventArgs e)
{
this.DoSomethingWithNewState(e.ConnectionState);
}
It can also be passed in to other objects as part of their constructor and so
on. (I suppose it could be fairly easily turned into a singleton too if you had
the need...)