2011-01-24 8 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サービス上で動作エラー処理を実装しようとしています。私は

[AErrorHandlerBehavior] 
public class AService : IAService 
{ 

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

     ....//various methods 
} 

しかしサービス内アイログ変数を宣言する場合、これはアイログ変数は、ロギングが動作しなくなったと宣言されていない場合、正常に動作します。

[AErrorHandlerBehavior] 
public class AService : IAService 
{ 

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

     ....//various methods 
} 

理想的には私は、それがすでに動作中で宣言されている場合は特に、私が作るすべてのサービスにアイログ変数を宣言する必要がありますする必要はありません。

誰かがa)行動とサービスの両方でこれを宣言しなければならない理由を説明してください。 b)二重宣言を避ける方法またはc)wcfへのよりよいログイン方法。

答えて

2

私はあなたがLogオブジェクトことを解決するために使用しているコードの確信していない:それは最初の自動車を解決するよう

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

これは常にコードの行が書かれている範囲内のタイプに解決されます定義された静的コンストラクタ(周囲のクラスの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、返信いただきありがとうございます。私はサービス記述を得る方法を見て苦労しています。これをどうやって取得するのかについてのポインターがあります。私が実際にやっていることは、エラーがスローされる最初の場所を得ることです。私は、これはエラーが動作にスローされているログを記録すると、これは少し難しいかもしれないと感じている。どちらが当然意味がありますが、私が欲しいものではない – KiwiInLondon

+0

実際に私は少し太くなっていましたが、朝早く少し早くなければなりません。今私はserviceDescriptionパラメータを参照してください。眼鏡をかけなければならない。ご協力いただきありがとうございます – KiwiInLondon

0

実際の問題は、ロガーを取得する正しい方法を無視すると、ロガーを構成していなかったという動作です。

修正がApplyDispatchBehavior

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

に設定文を追加するだけだった私は、サービス内のILogの宣言は、ロガーの構成を引き起こしたので、私はこれなしでbehaiourからログインしなかった理由だった推測しますエラーがスローされた前に