2011-01-24 2 views
1

은 내가 다음 동작을 사용하는 서비스를 구현 예외를WCF, IErrorHandler 및 log4Net

[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; 
    } 
} 

를 기록하는 log4net을 사용하는 WCF 서비스에서 오류 처리 동작을 구현하려합니다. 이 서비스 내에서 ILog 변수를 선언하면 정상적으로 작동합니다.

[AErrorHandlerBehavior] 
public class AService : IAService 
{ 

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

     ....//various methods 
} 

그러나 ILog 변수가 선언되지 않으면 로깅이 작동을 멈 춥니 다.

[AErrorHandlerBehavior] 
public class AService : IAService 
{ 

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

     ....//various methods 
} 

이상적으로 나는 그것이 이미 행동 선언, 특히 내가 생산하는 모든 서비스에 ILOG 변수를 선언하고 싶지 않아요.

누군가 설명해 주시겠습니까? a) 행동과 서비스에서 모두 선언되어야하는 이유. b) 이중 선언을 피하는 방법 또는 c) wcf에 로그인하는 더 좋은 방법. 처음 자동차를 해소 할

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

이 항상 코드의 라인이 기록 된 내 타입으로 해결할 수 :

답변

2

나는 당신이 그 Log 객체를 해결하는 데 사용하는 코드의 확신 아니에요 정의 된 정적 생성자 (주변 클래스의 MethodInfo.GetCurrentMethod())를 선언 한 다음 선언 유형을 가져옵니다.

글쎄, 나는 그것이 암시 물리적 때문에 자신을 작성 (그리고하지 않은 코드를 컴파일러의 내부 기능을 의존 나는 패턴의이 종류를 좋아하지 않는다

항상 말 ... 그 언제든지 변경); 명시 적으로 정적 생성자에 배치하면 자신이 작성하는 것이 더 좋을 것입니다. 이 작업을 수행하려면

, 다음 컴파일러와 런타임에 의존하지 않는 ...

typeof(_whatever_type_you_declare_it_in_); 

를 사용합니다.

똑같이 - 나는 속성이 정의 된 서비스로 해석 될 것이라는 잘못된 믿음으로이 패턴을 사용하고 있을지도 모른다.

행동 수준 기본값과 함께 서비스 수준에서 사용할 로그를 제어 할 수 있습니까?이렇게

1) 당신의 행동에 인스턴스 레벨 ILog 속성을 추가 ApplyDispatchBehaviour의 구현에서) _serviceLog

2라고 :

_serviceLog = LogManager.GetLogger(serviceDescription.ServiceType); 

그렇다면, 나는 당신을 제안

3) 그러면 HandleError의 구현은 다음과 같을 수 있습니다.

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; 
} 
+0

Andras, 답장을 보내 주셔서 감사합니다. 서비스 설명을받는 방법을보기 위해 고심하고 있습니다. 이것을 얻을 수있는 방법에 대한 포인터의 기회. 내가 실제로하려고하는 것은 오류가 던져지는 초기 장소를 얻는 것이다. 이 오류가 동작에 throw됩니다 로깅을보고있는 로그를 보는 것처럼 약간 어려울 수 있습니다 느낌이 있습니다. 어느 쪽이 의미가 있지만, 내가 원하는 것을 isnt한다 실제로 조금 두꺼운 것이었던 – KiwiInLondon

+0

는 아침에 약간 빨라야한다. 이제 serviceDescription 매개 변수가 표시됩니다. 안경을 써야합니다. 당신의 도움을 주셔서 감사합니다 – KiwiInLondon

0

로거를 얻는 올바른 방법을 무시하고 실제 문제는 로거를 구성하지 않은 동작입니다.

수정 내가 서비스 ILOG에 대한 선언이 로거의 구성 원인 때문이었다없이 나는 behaiour에서 로그인 할 수있는 이유를 추정 ApplyDispatchBehavior

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

로 구성 문을 추가 단순히이었다 오류가 던져지기 전에