我在IIS中托管了WCF服务:
[WebServiceLogging]
public class ComplaintService : IComplaintService
此服务具有WebServiceLogging
属性,可以直接将请求/响应记录到数据库中:
public class WebServiceLoggingAttribute : Attribute, IServiceBehavior {
SomeDatabaseConnection connection; // unmanaged resource
... interface implementations
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) {
IDispatchMessageInspector messageInspector = new WebServiceLogger(connection, _operations);
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints)
{
DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
dispatchRuntime.MessageInspectors.Add(messageInspector); // pass the logger into WCF.
}
}
}
}
记录工作是从WebServiceLogger
完成的,SomeDatabaseConnection
使用public class WebServiceLogger : IDispatchMessageInspector {
public object AfterReceiveRequest {
... gather Request data.
}
public void BeforeSendReply {
... gather Request data.
... Log using ADO.NET
... Dispose of Command object. No Connection closing!
}
}
非托管资源:
WebServiceLogger
我完成日志记录后,我需要在IDisposable
内关闭连接。我发现的选项是:
WebServiceLogging
课程上实施Dispose()
并在那里SomeDatabaseConnection
或WebServiceLogger.BeforeSendReply()
IDispatchMessageInspectors
醇>
我的问题是:
WebServiceLogger
的dispatchRuntime.MessageInspectors
(例如Attribute
) - 我注意到每个请求都没有重新创建此对象,而是在我的服务的第一个请求中只重复一次。这些物品是如何处置的? WCF会对它们调用“Dispose()˙还是应该在这里使用其他方法?”c# attribute dispose
中使用非托管资源可能并不是一个好主意。谷歌搜索FileSet
没有产生任何结果(虽然析构函数有一个结果)。对这种方法有任何批评吗?答案 0 :(得分:2)
打开并关闭BeforeSendReply
方法内的连接;即使它成为局部变量(带using
- 块等)。
这样的事情:
public void BeforeSendReply {
... gather Request data.
using (var conn = new SqlConnection(...)) {
... Log using ADO.NET
}
}
开销通常无关紧要(因为ADO.NET使用连接池,并且不会真正打开/关闭全新的连接)。其次,最重要的是,您不必考虑如何在多线程(并行请求)场景中使用/调用拦截器实例。
这也更好地匹配工作单元模式,如果你在OperationContract的实现方法中做同样的事情,通常会使用它。如果你考虑一下,拦截器点(AfterReceiveRequest
和BeforeSendReply
)实际上只是这种方法实现的扩展(类似AOP)。