每次调用我的Web服务时,我都想记录所调用方法的名称以及调用数据。
要写入此文件,我使用Nlog但我不希望在每个服务操作中进行日志记录调用。我更愿意以某种方式自动化这个日志记录调用作为交叉问题。
有可能吗?
答案 0 :(得分:2)
您可以使用支持拦截器的DI容器来记录任何带有输入值的WCF方法调用。以下是Ninject
和旧的奇怪ASMX服务的示例(对于WCF,想法是相同的):
让我们考虑以下客户端类:
public partial class LegacyClient : System.ServiceModel.ClientBase<Legacy>, Legacy
因为这个类是部分的,所以我们可以轻松地将包含我们想要调用的方法的接口ILegacyClient
添加到类中。 ReSharper在一秒钟内提取界面。所以将部分类声明放在单独的文件中:
public partial class LegacyClient : ILegacyClient {}
在DI配置中,添加拦截器:
Kernel.Bind(typeof(ILegacyClient))
.To<LegacyClient>()
.InRequestScope() //carefully choose a scope
.Intercept()
.With<LogRequestInterceptor>();
LogRequestInterceptor
是最有趣的部分:
using Ninject;
using Ninject.Extensions.Interception;
public class LogRequestInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
MethodInfo method = invocation.Request.Method;
var parameters = method.GetParameters();
var builder = new StringBuilder();
for (int index = 0; index < parameters.Length; index++)
{
object argument = invocation.Request.Arguments[index];
ParameterInfo parameterInfo = parameters[index];
if (!parameterInfo.IsOut)
{
//use any serialization you like
string text = $"{parameterInfo.Name} = {argument.ToJson()}, ";
builder.Append(text);
}
}
string joinedParameters = builder.ToString();
YourLogging(method.Name, joinedParameters);
//LegacyClient method call, don't forget this line
invocation.Proceed();
}
}
使事情有效的最后一部分。通过DI创建代理对象并使用它:
ILegacyClient client = Kernel.GetService<ILegacyClient>();
client.AnyMethodCall(...);
直接创建只是一个示例,当然您可以使用构造函数或属性注入,并在需要时将客户端接口替换为工厂。
希望它有所帮助!
答案 1 :(得分:1)
您可以尝试使用Windsor Castle,PostSharp或其他提供AOP的第三方库来进行面向方面编程(AOP)。此外,您可以使用这些库中的拦截器。
WCF Extension可能是另一个进行此类记录的地方。
使用WCF跟踪。您可以通过配置启用WCF跟踪来查看服务调用,消息级别详细信息等。
答案 2 :(得分:0)
来自 Agalo 的回答是正确的但是过于笼统,所以我只想添加一个如何实现#2的链接。我想这正是作者想要的问题。
简而言之,您可以实现自己的参数检查器(IParameterInspector
)并使用服务行为(IServiceBehavior
)注入它。 Here you can find complete example how to do that用于记录。