gpt4 book ai didi

c# - WCF 服务宿主何时销毁自定义 IDispatchMessageInspector?

转载 作者:太空宇宙 更新时间:2023-11-03 11:19:22 26 4
gpt4 key购买 nike

我已经创建了 IDispatchMessageInspector 接口(interface)的自定义实现,我的代码工作正常 99%。

我的问题是,当 WCF 服务主机被终止和/或释放我的类的一个实例时,我需要释放一些托管对象。我的对象免费实现 IDisposable 但它们没有被处置。我已经浏览过 MSDN 库(更困惑)和 SO 文件,但没有找到任何解决问题“WCF 服务主机何时/何地销毁 MessageInspectors?”

我需要在某个地方 Hook 一个事件吗?我是否需要从 ServiceModel 命名空间实现更神秘的东西?

谁能给我一个正确方向的指示?

编辑 1:澄清

目前,我正在使用自动网络服务器在 IDE 中运行。一旦投入生产,我最终无法控制主机,可能是任何有效的服务器主机选择。

MyCore.My 和 MyCore.MyProperties 对象是我在 WCF 服务器主机被终止/退回时尝试处理的对象。

即使我终止了网络服务器进程(任务栏中的那些东西),也永远不会调用 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 */);
}
}
}

最佳答案

我一直在查看 DispatchMessageInspector 及其实现方式。

正如您可能知道的那样,您使用 IEndpointBehavior 注册了 MessageInspector(通过配置或代码添加端点行为)。您在 EndpointBehaviour 中创建 DispatchMessageInspector 的实例。

   public class MyBehaviour : IEndpointBehavior
{

public void AddBindingParameters(ServiceEndpoint endpoint,
System.ServiceModel.Channels.BindingParameterCollection
bindingParameters)
{
}

public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{

}

public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
var inspector = new SampleMessageInspector(); //register
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}

public void Validate(ServiceEndpoint endpoint)
{
}

}

根据 http://msdn.microsoft.com/en-us/magazine/cc163302.aspx端点行为由服务主机注册

These behavior collections are automatically populated during the ServiceHost and ChannelFactory construction process with any behaviors that are found in your code (via attributes) or within the configuration file (more on this shortly). You can also add behaviors to these collections manually after construction. The following example shows how to add the ConsoleMessageTracing to the host as a service behavior:

ServiceHost host = new ServiceHost(typeof(ZipCodeService)); host.Description.Behaviors.Add(new ConsoleMessageTracing());

并进一步规定 ServiceHost 的生命周期与服务...

ServiceHost extension objects remain in memory for the lifetime of the ServiceHost while InstanceContext and OperationContext extension objects only remain in memory for the lifetime of the service instance or operation invocation. Your custom dispatcher/proxy extensions can use these collections to store (and look up) user-defined state throughout the pipeline.

我假设这就是为什么您的 MessageInspector 中的对象永远不会被销毁的原因。

有些人会认为它是一种反模式,但我可能会推荐一个 ServiceLocator,您的 MessageInspector 可以使用它来检索对象。然后,您可以考虑将它们的生命周期设置为与其父用法一样长吗?

    public class SampleMessageInspector : IDispatchMessageInspector
{

public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
{
var objectToDispose = ServiceLocator.Current.GetInstance<ObjectToDispose>();

//do your work
return null;
}

public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
//do some other work
}
}

继续我提到的...

作为示例,这篇文章提到使用 Ninject 作为 IoC 容器并将对象的生命周期设置为 WCF 服务的生命周期

Bind(...).To(...).InScope(() => OperationContext.Current)

Ninject WCF Garbage Collection on repositories

然后您可以通过 ServiceLocator 访问 Ninject Kernal,对象(_MyProperties 等...)将被处理掉

关于c# - WCF 服务宿主何时销毁自定义 IDispatchMessageInspector?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11526996/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com