2010-11-10 9 views
6

Szukałem wszędzie, aby dowiedzieć się, jak złapać typ umowy o wadę podstawy w C#. Chciałbym, aby wszystkie moje umowy o błędach dziedziczyły z jednej klasy i miały jeden połów (FaultException fex) w kontrolerze MVC.C# WCF catch Fault Wyjątki typu Base

DataContracts

[DataContract] 
public class BaseClass1 
{ } 

[DataContract] 
public class Class2 : BaseClass1 
{ } 

serwisowe

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

usługi Consumer

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

Proszę dać mi znać, jeśli każde z tych stwierdzeń połowowych można naprawić, aby zrobić to, czego szukam.

Odpowiedz

2

Niestety, nie ma sposobu, aby to zrobić. Nie ma żadnego związku między FaultException<T1> i FaultException<T2> po prostu dlatego, że T1 może być podklasą T2.

+0

Ale jaki jest powód takiego zachowania? –

5

Ta składnia nie zadziała w języku C#. Zamiast tego należy rozważyć następujące "obejście".

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. 
} 

ten można uprościć, jeśli pominąć niezwykłego przypadku, gdy Detail == null ale zbudowane generyczne mecze typu. Będę również używał słowa kluczowego dynamicznego C#, aby nieco go uprościć.

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. 
} 

Inną rzeczą do rozważenia jest, czy należy po prostu użyć throw new FaultException<BaseClass1>(new DerivedClass2()). Ten sposób rzucania pozwoli Ci złapać za pomocą kodu, który pierwotnie dostarczyłeś.