我需要在WCF服务中记录每个方法调用,并抛出任何异常。这导致了大量冗余代码,因为每个方法都需要包含类似于此的样板:
[OperationContract]
public ResultBase<int> Add(int x, int y)
{
var parameters = new object[] { x, y }
MyInfrastructure.LogStart("Add", parameters);
try
{
// actual method body goes here
}
catch (Exception ex)
{
MyInfrastructure.LogError("Add", parameters, ex);
return new ResultBase<int>("Oops, the request failed", ex);
}
MyInfrastructure.LogEnd("Add", parameters);
}
有没有办法可以将所有这些逻辑封装到属性MyServiceLoggingBehaviorAttribute
中,我可以将其应用于这样的服务类(或方法):
[ServiceContract]
[MyServiceLoggingBehavior]
public class MyService
{
}
注意#1
我意识到这可以使用Aspect-oriented programming完成,但在C#中,唯一的方法是修改字节码,这需要使用像PostSharp这样的第三方产品。我想避免使用商业图书馆。
注意#2
请注意,Silverlight应用程序是该服务的主要使用者。
注意#3
WCF trace logging在某些情况下是一个不错的选择,但它在这里不起作用,因为如上所述,我需要检查,并且在异常更改的情况下,返回值。
答案 0 :(得分:26)
是的,可以使用extensibility points built into WCF封装此类日志记录。实际上有多种可能的方法。我在这里描述的那个添加IServiceBehavior
,它使用自定义IOperationInvoker
,并且不需要任何web.config修改。
这有三个部分。
IOperationInvoker
的实现,它将方法调用包装在所需的日志记录和错误处理中。IOperationBehavior
的实现,该实现应用步骤1中的调用者。IServiceBehavior
的{{1}},并应用第2步中的行为。 IOperationInvoker的关键是Attribute
方法。我的类将基本调用程序包装在try-catch块中:
Invoke
IOperationBehavior的实现只是将自定义调度程序应用于操作。
public class LoggingOperationInvoker : IOperationInvoker
{
IOperationInvoker _baseInvoker;
string _operationName;
public LoggingOperationInvoker(IOperationInvoker baseInvoker, DispatchOperation operation)
{
_baseInvoker = baseInvoker;
_operationName = operation.Name;
}
// (TODO stub implementations)
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
MyInfrastructure.LogStart(_operationName, inputs);
try
{
return _baseInvoker.Invoke(instance, inputs, out outputs);
}
catch (Exception ex)
{
MyInfrastructure.LogError(_operationName, inputs, ex);
return null;
}
MyInfrastructure.LogEnd("Add", parameters);
}
}
public class LoggingOperationBehavior : IOperationBehavior
{
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.Invoker = new LoggingOperationInvoker(dispatchOperation.Invoker, dispatchOperation);
}
// (TODO stub implementations)
}
的此实现将操作行为应用于服务;它应该从IServiceBehavior
继承,以便它可以作为属性应用于WCF服务类。这方面的实施是标准的。
Attribute
答案 1 :(得分:3)