C# WCF ловит Fault Исключения Базового типа
Я искал везде, чтобы узнать, как поймать базовый тип контракта ошибки в C#. Я хотел бы, чтобы все мои контракты с ошибками наследовались от одного класса и имели один улов (FaultException fex) в контроллере MVC.
DataContracts
[DataContract]
public class BaseClass1
{ }
[DataContract]
public class Class2 : BaseClass1
{ }
обслуживание
[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");
}
}
Потребитель услуг
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>
}
Пожалуйста, дайте мне знать, можно ли исправить одно из этих операторов catch для выполнения того, что я ищу.
3 ответа
Этот синтаксис не будет работать в C#. Рассмотрим следующий "обходной путь".
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.
}
Это может быть упрощено, если мы игнорируем необычный случай, когда Detail == null
но созданный общий тип совпадает. Я также буду использовать динамическое ключевое слово C#, чтобы немного упростить его.
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.
}
Другая вещь, чтобы рассмотреть, следует ли вам просто использовать throw new FaultException<BaseClass1>(new DerivedClass2())
, Этот способ броска позволит вам ловить, используя код, который вы изначально предоставили.
Извините, нет способа сделать это. Там нет никакой связи между FaultException<T1>
а также FaultException<T2>
просто потому что T1
может быть подклассом T2
,
Вашему клиенту нужен инспектор сообщений. У нас была похожая ситуация, когда сервер генерировал различные исключения, и все они заканчивались как FaultException.