IDispatchMessageInspectorインターフェイスのカスタム実装を作成しましたが、コードは99%正常に機能しています。
私の問題は、WCFサービスホストが強制終了されたとき、および/またはクラスのインスタンスを解放したときに、いくつかの管理対象オブジェクトを解放する必要があることです。IDisposableを解放するための私のオブジェクトは、破棄されていません。私はMSDNライブラリ(もっと混乱しています)とSOアーカイブを調べましたが、「WCFサービスホストがMessageInspectorsを破棄するのはいつ/どこですか?」という質問に対処するものは見つかりませんでした。
イベントをどこかにフックする必要がありますか?ServiceModel名前空間からさらに難解なものを実装する必要がありますか?
誰かが私に正しい方向へのポインタを与えることができますか?
編集1:説明
現在、自動Webサーバーを使用してIDEで実行しています。私は、本番環境で一度ホストを制御することはできません。有効なサーバーホストの選択肢のいずれかである可能性があります。
MyCore.MyオブジェクトとMyCore.MyPropertiesオブジェクトは、WCFサーバーホストが強制終了/バウンスされたときに破棄しようとしているオブジェクトです。
Webサーバープロセス(タスクバーにあるもの)を強制終了した場合でも、Dispose()が呼び出されることはありません。
編集2:コードスニペットが追加されました。
using /* snip */
using MyCore = Acme.My;
namespace My.SOAP
{
public class MyMessageInspector : IDispatchMessageInspector
{
protected static MyCore.My _My;
protected static MyCore.MyProperties _MyProps;
protected static ConcurrentDictionary<string, MyCore.AnotherSecretThing> _anotherSecretThings = new ConcurrentDictionary<string, MyCore.AnotherSecretThing>();
protected static void InitMy()
{
if (_My != null) return;
_MyProps = new MyCore.MyProperties();
MyCore.MySqlDatabaseLogger logger = new MyCore.MySqlDatabaseLogger(_MyProps);
_My = new MyCore.My(logger);
}
public MyMessageInspector()
{
InitMy();
}
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
MyMessageHeader header = null;
try
{
// find My header
Int32 headerPosition = request.Headers.FindHeader(MyMessageHeaderKey.MyHeaderElementName, MyMessageHeaderKey.MyNamespace);
// get reader
XmlDictionaryReader reader = request.Headers.GetReaderAtHeader(headerPosition);
// get My header object
header = MyMessageHeader.ReadHeader(reader);
// add to incoming messages properties dictionary
OperationContext.Current.IncomingMessageProperties.Add(MyMessageHeaderKey.MyHeaderElementName, header);
}
catch (Exception ex)
{
// log via ExceptionHandlingBlock
}
MyCore.SecretThings SecretThings = CreateSecretThings(/* snip */);
return SecretThings.Id;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
MyCore.SecretThings req = _My.GetSecretThingsOnThread();
// if we didn't find the SecretThings, there is nothing to stop() and no data to put in the MessageHeaders
if (req == null) return;
MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
reply = buffer.CreateMessage();
var MyHeader = new MyMessageHeader(/* snip */);
reply.Headers.Add(MyHeader);
req.Stop(MyCore.Status.SUCCESS);
}
protected MyCore.SecretThings CreateSecretThings(string key, Dictionary<string, string> ids)
{
/* snip */
return _My.GetSecretThings(/* snip */);
}
}
}