我一直在寻找如何在c#中捕获基本错误契约类型。我希望我的所有错误契约都从一个类继承,并在MVC控制器中有一个catch(FaultException fex)。
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>
}
如果可以修复这些捕获语句中的任何一个来执行我正在寻找的内容,请告诉我。
答案 0 :(得分:5)
该语法在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())
。这种投掷方式可以让你使用最初提供的代码。
答案 1 :(得分:2)
抱歉,没有办法做到这一点。 FaultException<T1>
与FaultException<T2>
之间没有任何关系,因为T1
可能是T2
的子类。
答案 2 :(得分:0)
您的客户需要message inspector。我们有一个类似的situation,其中服务器抛出各种异常,它们最终都是一个FaultException。