2010-11-10 2 views
6

J'ai cherché partout comment trouver un type de contrat de défaut de base dans C#. Je voudrais que tous mes contrats d'erreur héritent d'une classe et aient un catch (FaultException fex) dans le contrôleur MVC.C# WCF catch Fault Exceptions du type de base

DataContracts

[DataContract] 
public class BaseClass1 
{ } 

[DataContract] 
public class Class2 : BaseClass1 
{ } 

service

[ServiceContract] 
public interface IService1 
{ 
    [OperationContract] 
    [FaultContract(typeof(BaseClass1))] 
    [FaultContract(typeof(Class2))] //Do I need this one? 
    void ThrowClass2(); 
} 

public class Service1 : IService1 
{ 
    public void ThrowClass2() 
    { 
     throw new FaultException<Class2>(new Class2(), "Class2 Reason"); 
    } 
} 

Service aux consommateurs

FaultTestService.Service1Client client = null; 
try 
{ 
    client = new FaultTestService.Service1Client(); 
    client.ThrowAmpFaults("InvalidParameter", 0); 
} 
catch (FaultException<Namespace.BaseClass1> fex) 
{ 
    //DOES NOT GO IN HERE AS I WOULD EXPECT 
} 
catch (FaultException fex) 
{ 
    //Other Possible Option 
    MessageFault fault = fex.CreateMessageFault(); 
    var fe1 = fault.GetDetail<BaseClass1>(); 
    //This throws a serialization exception it needs <Class2> 
} 

S'il vous plaît laissez-moi savoir si l'un ou l'autre de ces énoncés peut être corrigé pour faire ce que je cherche.

Répondre

2

Désolé, il n'y a aucun moyen de le faire. Il n'y a pas de relation entre FaultException<T1> et FaultException<T2> simplement parce que T1 peut être une sous-classe de T2.

+0

Mais quelle est la raison de ce comportement? –

5

Cette syntaxe ne fonctionnera pas en C#. Considérez la "solution de contournement" suivante à la place.

try 
{ 
    throw new FaultException<DerivedClass2>(new DerivedClass2()); 
} 
catch (FaultException fex) 
{ 
    bool handled = false; 
    Type fexType = fex.GetType(); 
    if (fexType.IsGenericType && fexType.GetGenericTypeDefinition() == typeof(FaultException<>)) 
    { 
     if (typeof(BaseClass1).IsAssignableFrom(fexType.GetGenericArguments()[0])) 
     { 
      object detail = fexType.GetProperty("Detail").GetValue(fex, null); 

      // Use detail here. 

      handled = true; 
     } 
    } 

    if (!handled) 
     throw; // Don't know how to handle. Re-throw. 
} 

Cela peut être simplifiée si l'on fait abstraction du cas inhabituel où Detail == null mais les matchs de type générique construit. J'utiliserai également le mot clé dynamique C# pour le simplifier un peu plus.

try 
{ 
    throw new FaultException<DerivedClass2>(new DerivedClass2()); 
} 
catch (FaultException fex) 
{ 
    bool handled = false; 
    Type fexType = fex.GetType(); 
    if (fexType.IsGenericType && fexType.GetGenericTypeDefinition() == typeof(FaultException<>)) 
    { 
     object detail = ((dynamic)fex).Detail; 
     if (detail is BaseClass1) // true for subclasses too! 
     { 
      // Use detail here. 
     } 

    } 

    if (!handled) 
     throw; // Don't know how to handle. Re-throw. 
} 

L'autre chose à considérer est de savoir si vous devez simplement utiliser throw new FaultException<BaseClass1>(new DerivedClass2()). Cette façon de lancer vous permettra d'attraper en utilisant le code que vous avez fourni à l'origine.

0

Votre client a besoin d'un message inspector. Nous avons eu un situation similaire où le serveur lançait diverses exceptions et ils ont tous fini comme une exception FaultException.