你也可以使用“适配器”来抽象化许多其他事件。
例如,从我的一个项目中...
#region Copyright
#endregion
namespace Media.Sockets
{
#region NetworkConnection
public class NetworkConnection : Connection, Common.ISocketReference
{
#region NetworkConnectionState
[System.Flags]
protected enum NetworkConnectionState : long
{
None = 0,
Initialized = 1,
Bound = 2,
Connected = 4,
}
#endregion
#region Fields
Common.Extensions.WaitHandle.DisposableWaitHandle WaitHandle;
protected System.DateTime LasRemoteConnectionStartedDateTime;
protected System.DateTime LastRemoteConnectionCompletedDateTime;
#endregion
#region Properties
public System.TimeSpan RemoteConnectionTime { get { return LastRemoteConnectionCompletedDateTime - LasRemoteConnectionStartedDateTime; } }
public System.Net.NetworkInformation.NetworkInterface NetworkInterface { get; protected set; }
public System.Net.Sockets.Socket ConnectionSocket { get; protected set; }
public bool HasNetworkInterface { get { return NetworkInterface != null; } }
public System.Net.EndPoint LocalEndPoint { get; protected set; }
public bool HasLocalEndPoint { get { return LocalEndPoint != null; } }
public System.Net.EndPoint RemoteEndPoint { get; protected set; }
public bool HasRemoteEndPoint { get { return RemoteEndPoint != null; } }
protected NetworkConnectionState NetworkConnectionFlags
{
get { return (NetworkConnectionState)Flags; }
set { Flags = (long)value; }
}
#endregion
#region Constructor
public NetworkConnection()
: base() { }
public NetworkConnection(string name, bool shouldDispose)
: base(name, shouldDispose) { }
public NetworkConnection(System.Net.Sockets.Socket existingSocket, bool ownsHandle, bool shouldDispose)
: this("System.Net.Socket-" + ownsHandle.ToString(), shouldDispose)
{
if (existingSocket == null) throw new System.ArgumentNullException("existingSocket");
ConnectionSocket = existingSocket;
FlagInitialized();
NetworkInterface = Common.Extensions.NetworkInterface.NetworkInterfaceExtensions.GetNetworkInterface(ConnectionSocket);
CreateWaitHandle(ConnectionSocket.Handle, ownsHandle);
if (ConnectionSocket.IsBound)
{
FlagBound();
LocalEndPoint = existingSocket.LocalEndPoint;
}
if (ConnectionSocket.Connected)
{
LasRemoteConnectionStartedDateTime = System.DateTime.UtcNow;
RemoteEndPoint = existingSocket.RemoteEndPoint;
Connect();
LastRemoteConnectionCompletedDateTime = System.DateTime.UtcNow;
}
}
#endregion
#region NetworkChange Event Handlers
void NetworkChange_NetworkAvailabilityChanged(object sender, System.Net.NetworkInformation.NetworkAvailabilityEventArgs e)
{
Refresh();
}
void NetworkChange_NetworkAddressChanged(object sender, System.EventArgs e)
{
Refresh();
}
#endregion
#region Bound
protected void FlagBound()
{
Flags |= (long)NetworkConnectionState.Bound;
}
protected void UnFlagBound()
{
Flags &= (long)NetworkConnectionState.Bound;
}
#endregion
#region Initialize
protected void FlagInitialized()
{
Flags |= (long)NetworkConnectionState.Initialized;
}
protected void UnFlagInitialized()
{
Flags &= (long)NetworkConnectionState.Initialized;
}
public virtual void Initialize(bool registerForEvents)
{
if (false == NetworkConnectionFlags.HasFlag(NetworkConnectionState.Initialized))
{
FlagInitialized();
if (registerForEvents)
{
System.Net.NetworkInformation.NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged;
System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged;
}
}
}
#endregion
#region Refresh
public override void Refresh()
{
base.Refresh();
}
#endregion
#region CreateConnectionSocket
public void CreateConnectionSocket(System.Net.Sockets.AddressFamily addressFamily, System.Net.Sockets.SocketType socketType, System.Net.Sockets.ProtocolType protocolType)
{
if (ConnectionSocket == null)
{
ConnectionSocket = new System.Net.Sockets.Socket(addressFamily, socketType, protocolType);
CreateWaitHandle(ConnectionSocket.Handle, true);
}
}
#endregion
#region CreateWaitHandle
public void CreateWaitHandle(System.IntPtr handle, bool ownsHandle)
{
if (WaitHandle == null)
{
WaitHandle = new Common.Extensions.WaitHandle.DisposableWaitHandle(handle, ownsHandle);
}
}
#endregion
#region Connect
protected void FlagConnected()
{
Flags |= (long)NetworkConnectionState.Connected;
}
protected void UnFlagConnected()
{
Flags &= (long)NetworkConnectionState.Connected;
}
public override void Connect()
{
if (false == NetworkConnectionFlags.HasFlag(NetworkConnectionState.Connected))
{
if (IsEstablished) return;
if (NetworkInterface == null) throw new System.InvalidOperationException("NetworkInterface must be assigned before calling Connect.");
if (LocalEndPoint == null) throw new System.InvalidOperationException("LocalEndPoint must be assigned before calling Connect.");
if (RemoteEndPoint == null) throw new System.InvalidOperationException("RemoteEndPoint must be assigned before calling Connect.");
base.Connect();
FlagConnected();
Refresh();
}
}
public virtual void Connect(System.Net.Sockets.AddressFamily addressFamily, System.Net.Sockets.SocketType socketType, System.Net.Sockets.ProtocolType protocolType, System.Net.IPAddress[] addressList, int port)
{
try
{
CreateConnectionSocket(addressFamily, socketType, protocolType);
LasRemoteConnectionStartedDateTime = System.DateTime.UtcNow;
ConnectionSocket.Connect(addressList, port);
LastRemoteConnectionCompletedDateTime = System.DateTime.UtcNow;
}
finally
{
NetworkInterface = Common.Extensions.NetworkInterface.NetworkInterfaceExtensions.GetNetworkInterface(ConnectionSocket);
LocalEndPoint = (System.Net.IPEndPoint)ConnectionSocket.LocalEndPoint;
RemoteEndPoint = (System.Net.IPEndPoint)ConnectionSocket.RemoteEndPoint;
Connect();
}
}
#endregion
#region Disconnect
public virtual void Disconnect(bool allowReuse = false)
{
if (((NetworkConnectionState)Flags).HasFlag(NetworkConnectionState.Connected))
{
ConnectionSocket.Disconnect(allowReuse);
base.Disconnect();
UnFlagConnected();
Refresh();
}
}
public override void Disconnect()
{
Disconnect(false);
}
#endregion
#region Dispose
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
using (WaitHandle)
{
System.Net.NetworkInformation.NetworkChange.NetworkAddressChanged -= NetworkChange_NetworkAddressChanged;
System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged -= NetworkChange_NetworkAvailabilityChanged;
ConnectionSocket = null;
LocalEndPoint = RemoteEndPoint = null;
NetworkInterface = null;
}
}
#endregion
System.Collections.Generic.IEnumerable<System.Net.Sockets.Socket> Common.ISocketReference.GetReferencedSockets()
{
yield return ConnectionSocket;
}
}
#endregion
}
如果您需要“Connection”基类,可以引用此内容。
#region Copyright
#endregion
namespace Media.Sockets
{
#region Connection
public abstract class Connection : Common.BaseDisposable
{
#region Statics
const string FormatString = "{0} {1} ({2}) {3}";
#endregion
#region Properties
public readonly System.Guid Id = System.Guid.NewGuid();
public readonly System.DateTime Created = System.DateTime.UtcNow;
public readonly string Name;
public bool IsPersistent
{
get
{
return ShouldDispose == false;
}
set
{
ShouldDispose = value == false;
}
}
protected long Flags { get; set; }
public virtual bool IsEstablished { get; protected set; }
public System.DateTime EstablishedDateTime { get; protected set; }
public System.TimeSpan TimeEstablished { get { return IsEstablished ? System.DateTime.UtcNow - EstablishedDateTime : System.TimeSpan.Zero; } }
#endregion
#region Connect
public virtual void Connect()
{
if (IsDisposed) return;
EstablishedDateTime = System.DateTime.UtcNow;
IsEstablished = true;
}
#endregion
#region Disconnect
public virtual void Disconnect()
{
if (IsDisposed) return;
IsEstablished = false;
}
#endregion
#region Refresh
public virtual void Refresh()
{
CheckDisposed();
}
#endregion
#region Dispose
public override void Dispose()
{
if (IsDisposed) return;
if (false == IsPersistent) Disconnect();
base.Dispose();
}
#endregion
#region Constructor
public Connection(string name, bool shouldDispose)
: base(shouldDispose)
{
Name = name;
}
public Connection()
: this(string.Empty, true) { }
#endregion
#region ToString
public override string ToString()
{
return string.Format(FormatString, GetType().Name.ToString(), Id.ToString(), Flags, Name);
}
#endregion
}
#endregion
}