2011-02-03 2 views
1

WCF와 명명 된 파이프를 사용하는 간단한 IPC 메커니즘이 있습니다. 내 목표는 예외 정보 (스택 추적 포함)를 클라이언트에 로깅 목적으로 전파하는 것입니다 (나머지 응용 프로그램 로깅은 클라이언트에 있습니다).WCF FaultContract가 NamedPipe와 함께 실패 함

나는 예외 사항 클라이언트에 오류 예외 < 예외 >을 잡아 볼 수 있어요 다음 코드를 사용하는 경우 :

계약 :

[ServiceContract] 
public interface IService 
{ 
    [OperationContract] 
    [FaultContract(typeof(Exception))] 
    void DoSomething(); 
} 

구현 :

public class Service : IService 
{ 
    public void DoSomething() 
    { 
     try 
     { 
      ThisWillThrowAnException(); 
     } 
     catch (Exception e) 
     { 
      throw new FaultException<Exception>(e); 
     } 
    } 
} 

클라이언트 :

public void CallServer() 
{ 
    try 
    { 
     proxy.DoSomething(); 
    } 
    catch (FaultException<Exception> e) 
    { 
     Console.WriteLine("Caught fault exception!"); 
    } 
} 

잘 작동하고 메시지가 콘솔에 인쇄 된 것을 볼 수 있습니다. 그러나 기본 Exception 클래스 대신 자체 파생 된 예외를 사용하려면 실패합니다.

사용자 정의 예외 :

new FaultException<MyException>(new MyException(e.Message, e); 

변경 클라이언트 캐치 절에

typeof(MyException). 

변경 서비스에 던져 절에

[Serializable] 
public class MyException : Exception 
{ 
    public MyException() { } 
    public MyException (string message) : base(message) { } 
    public MyException (string message, Exception inner) : base(message, inner) { } 
    protected MyException (
     SerializationInfo info, 
     StreamingContext context) 
     : base(info, context) { } 
} 

변경 IService.DoSomething에 FaultContract ~

catch (FaultException<MyException> e) 

과 함께 CommunicationException이 catch됩니다. System.ServiceModel.CommunicationException : 파이프에서 읽는 중 오류가 발생했습니다. 파이프가 종료되었습니다. (109, 0x6d).

MyException 클래스는 클라이언트와 서버에서 모두 사용할 수있는 공유 라이브러리에 있습니다.

이 질문은 this question과 매우 비슷하지만 도움이되지 않았습니다.

답변

1

StackFrames의 직렬화 된 목록이 포함 된 자체 오류 DataContract를 작성하여이 문제를 해결했습니다.

분명히이 MSDN 기사는 정확하지 않습니까?

http://msdn.microsoft.com/en-us/library/ff649840.aspx

[DataContract] 
public class MyFault 
{ 
    [DataMember] 
    public string Message { get; set; } 

    [DataMember] 
    public IList<SerializableMiniStackFrame> StackTrace { get; set; } 


    public static MyFault CreateFault(Exception e) 
    { 
     MyFault fault = new MyFault(); 
     fault.Message = e.Message; 
     fault.InitTrace(e); 
     return fault; 
    } 

    /// <summary> 
    /// Initializes the stack trace based on when the inner exception was thrown. 
    /// </summary> 
    /// <param name="inner">The inner exception.</param> 
    private void InitTrace(Exception inner) 
    { 
     StackTrace trace = new StackTrace(inner, true); 
     InitTrace(trace); 
    } 

    /// <summary> 
    /// Initializes the internal serializable stack frames based on the given 
    /// stack trace. 
    /// </summary> 
    /// <param name="stackTrace">The stack trace.</param> 
    private void InitTrace(StackTrace stackTrace) 
    { 
     // Create a new list of serializable frames. 
     this.StackTrace = new List<SerializableMiniStackFrame>(); 
     // Iterate over each frame in the stack trace. 
     foreach (StackFrame frame in stackTrace.GetFrames()) 
     { 
      string type = ""; 
      Type declaringType = frame.GetMethod().DeclaringType; 
      if (null != declaringType) 
      { 
       type = declaringType.FullName; 
      } 

      MethodBase method = frame.GetMethod(); 
      string methodName = method.Name; 
      string parameters = string.Empty; 
      string delimiter = string.Empty; 
      foreach (ParameterInfo parameter in method.GetParameters()) 
      { 
       parameters += string.Format("{0}{1} {2}", delimiter, parameter.ParameterType.Name, parameter.Name); 
       delimiter = ", "; 
      } 
      string file = Path.GetFileName(frame.GetFileName()); 
      int line = frame.GetFileLineNumber(); 

      // Create a serializable frame and add it to the list. 
      SerializableMiniStackFrame miniFrame = new SerializableMiniStackFrame(type, methodName, parameters, file, line); 
      this.StackTrace.Add(miniFrame); 
     } 
    } 
} 

/// <summary> 
/// This class encapsulates basic stack frame information into a serializable 
/// object. 
/// </summary> 
[DataContract] 
public class SerializableMiniStackFrame 
{ 
    public SerializableMiniStackFrame() { } 
    public SerializableMiniStackFrame(string type, string method, string parameters, string file, int line) 
    { 
     this.Type = type; 
     this.Method = method; 
     this.Parameters = parameters; 
     this.File = file; 
     this.Line = line; 
    } 

    [DataMember] 
    public string Type { get; set; } 
    [DataMember] 
    public string Method { get; set; } 
    [DataMember] 
    public string Parameters { get; set; } 
    [DataMember] 
    public string File { get; set; } 
    [DataMember] 
    public int Line { get; set; } 
} 
관련 문제