WCF,IErrorHandler和log4Net [英] WCF, IErrorHandler and log4Net

查看:166
本文介绍了WCF,IErrorHandler和log4Net的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在将使用log4net记录异常的wcf服务上实现错误处理行为

I am trying to implement an error handling behavior on a wcf service that will use log4net to log an exception

[AttributeUsage(AttributeTargets.Class)]
public class AErrorHandlerBehaviorAttribute : Attribute, IServiceBehavior, IErrorHandler{

  private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

  protected Type ServiceType { get; set; }
  public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
  {
   //Dont do anything
  }

  public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection <ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
  {
   //dont do anything
  }

  public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
  {
   ServiceType = serviceDescription.ServiceType;
   foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
   {
    dispatcher.ErrorHandlers.Add(this);
   }
  }

  public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
  {
   fault = null; //Suppress any faults in contract
  }

  public bool HandleError(Exception error)
  {   
   log.Error("Page Load failed : " + error.Message); 
   return false;
  }
}

然后我实现使用该行为的服务.如果我在服务中声明ILog变量,则效果很好

I then implement a service that uses the behavior. This works fine if I declare the ILog variable within the service

[AErrorHandlerBehavior]
public class AService : IAService
{

     private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        ....//various methods
}

但是,当未声明ILog变量时,日志记录将停止工作.

However, when the ILog variable is not declared the logging stops working.

[AErrorHandlerBehavior]
public class AService : IAService
{

     //private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        ....//various methods
}

理想情况下,我不想在我生产的每个服务中都声明ILog变量,尤其是当行为中已经声明了它时.

Ideally I don't want to have to declare the ILog variable in every service I produce, especially when it is already declared in the behavior.

有人可以解释一下a)为什么必须在行为和服务中都声明这一点. b)避免重复声明的任何方式,或c)登录wcf的更好方式.

Could someone please explain a) why this has to be declared in both the behavior and in the service. and b) any way of avoiding the double declaration or c) a better way of logging in wcf.

推荐答案

我不相信您用来解析该Log对象的代码:

I'm not convinced of the code you're using to resolve that Log object:

private static readonly ILog log = 
  LogManager.GetLogger(
    System.Reflection.MethodBase.GetCurrentMethod().DeclaringType
  );

这将始终解析为编写代码行的类型,因为它首先解析了自动定义的静态构造函数(使用周围类的MethodInfo.GetCurrentMethod()),然后获取其声明类型.

This will always resolve to the type within which the line of code is written as it resolves first the auto-defined static constructor (with MethodInfo.GetCurrentMethod() of the surrounding class) and then gets its declaring type.

好吧,我总是说 ...

Well, I say always...

我不喜欢这种模式,因为它隐式依赖您尚未亲自编写的代码(因此是 可以 的编译器的内部功能) >随时更改);如果将其显式地放置在您自己编写的静态构造函数中,那会略胜一筹.

I don't like this kind of pattern as it implicitly relies on code that you haven't physically written yourself (and therefore an internal feature of the compiler that could change at any time); it would be marginally better if you explicitly placed it inside a static constructor you write yourself.

如果要执行此操作,请使用

If you want to do this, then use

typeof(_whatever_type_you_declare_it_in_);

...不依赖编译器和运行时.

... don't rely on the compiler and the runtime.

同样-我有一种感觉,您可能会误以为它会解析到定义了属性的服务,而不会解析.

Equally - I have a feeling you might be using this pattern under the mistaken belief that it'll resolve to the service on which the attribute is defined, it won't.

您是否打算能够以行为级别的默认值来控制要在服务级别使用的日志?

Is your intention to be able to control the log to be used at the service-level, with a behaviour-level default?

如果是这样,那么我建议你:

If so, then I suggest you:

1)将实例级别的ILog属性添加到您的行为中,称为_serviceLog

1) Add an instance-level ILog property to your behaviour, called _serviceLog

2)在ApplyDispatchBehaviour的实现中,请执行以下操作:

2) In your implementation of ApplyDispatchBehaviour do this:

_serviceLog = LogManager.GetLogger(serviceDescription.ServiceType);

3)然后,您对HandleError的实现可能如下:

3) And then your implementation of HandleError could be as follows:

public bool HandleError(Exception error)
{
  //use the service-level log, or a default
  ILog targetLog = _serviceLog ?? log;
  if(targetLog != null)
    targetLog.Error("Page Load failed : " + error.Message);
  return false;
}

这篇关于WCF,IErrorHandler和log4Net的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆