TcpClient クラスを使用してコマンドの接続と送受信を可能にするメール クライアント サービスを設計しようとしています。また、各関数のコールバック時に呼び出し元のスレッドを自動的に呼び出して、呼び出し元が必要ないようにしたいと考えています。
これを実装するには、関数ごとに少なくとも 3 倍から 4 倍多くのコードを記述する必要があることがわかっています。最大の問題は、コールバックごとに個別の try/catch を作成する必要があることです。
Connect 関数を投稿します。うまくいけば、誰かがより良い方法を提案できます。
public virtual void Connect(Action<Exception> callback, string hostname, int port, bool ssl, RemoteCertificateValidationCallback validateCertificate)
{
if (State != ConnectionState.Disconnected)
throw new InvalidOperationException(AlreadyConnectedString);
Host = hostname;
Port = port;
Ssl = ssl;
var context = SynchronizationContext.Current;
// Callback on the caller's thread
Action<Exception> onCallback = (Exception ex) =>
{
context.Post(_ =>
{
callback(ex);
}, null);
};
// Called on any raised exceptions
Action<Exception> onFail = (Exception ex) =>
{
State = ConnectionState.Disconnected;
Cleanup();
onCallback(ex);
};
// Check for a valid response
Action<string, Exception> onConnectResponse = (string response, Exception ex) =>
{
if (ex != null)
onFail(ex);
try
{
OnConnected(response);
onCallback(ex);
}
catch (Exception responseException)
{
onFail(responseException);
}
};
// Callback after SSL authentication
AsyncCallback onAuthenticated = (IAsyncResult result) =>
{
try
{
var sslStream = (SslStream)result.AsyncState;
sslStream.EndAuthenticateAsClient(result);
State = ConnectionState.Authorization;
GetResponse(onConnectResponse);
}
catch (Exception authenticateException)
{
onFail(authenticateException);
}
};
// Callback after TcpClient connect
AsyncCallback onConnect = (IAsyncResult result) =>
{
try
{
_Connection.EndConnect(result);
_Stream = _Connection.GetStream();
if (ssl)
{
SslStream sslStream;
if (validateCertificate != null)
sslStream = new SslStream(_Stream, false, validateCertificate);
else
sslStream = new SslStream(_Stream, false);
_Stream = sslStream;
sslStream.BeginAuthenticateAsClient(hostname, onAuthenticated, sslStream);
}
else
{
State = ConnectionState.Authorization;
GetResponse(onConnectResponse);
}
}
catch (Exception connectException)
{
onFail(connectException);
}
};
try
{
_Connection = new TcpClient();
_Connection.BeginConnect(hostname, port, onConnect, null);
}
catch (Exception ex)
{
onFail(ex);
}
}