我在这个设计中需要一个观点,我建议处理异常。
我有一个wcf服务,它会抛出不同类型的错误异常:
所有这些错误异常类都实现了一个名为IViolationFault的接口,该接口只有一个HandleException方法。每种这样的方法的实现取决于它们所在的类别;所以例如当客户端捕获这些异常类时,我需要做的只是调用HandleException()方法,并且我将不必编写IF条件来区分错误类型。在BusinessRuleViolationFault的HandleException()方法中,我可能只想在屏幕上显示一条消息,而在另一个方面我可能想在某处记录它并触发其他一些操作......
catch (FaultException<BusinessRuleViolationFault> ex)
{
ex.HandleException();
}
catch (FaultException<SomeOtherViolationFault> ex)
{
ex.HandleException();
}
问题
修改
我已将代码更改为从基类继承而不是实现接口。我的BusinessRuleViolationFault类具有HandleException方法,但我无法在客户端catch块中获取HandleException方法。怎么了?这是它在服务中抛出的方式
BusinessRuleViolationFault bf = new BusinessRuleViolationFault("");
throw new FaultException<BusinessRuleViolationFault>(bf, new FaultReason(new FaultReasonText("Fault reason here")));
这是我的BusinessRuleViolationFault代码
[DataContract]
public class BusinessRuleViolationFault : BaseFault
{
public BusinessRuleViolationFault(string message)
: base(message)
{
}
[OperationContract]
public override string HandleException()
{
return "BusinessRuleViolationFault executed";
}
}
[DataContract]
public abstract class BaseFault
{
public BaseFault(string message)
{
Message = message;
}
[DataMember]
public string Message { get; set; }
[OperationContract]
public abstract string HandleException();
}
请让我对此有所了解。谢谢你的时间......
答案 0 :(得分:1)
编辑:更正示例代码。
至少在WCF中,这是实现自定义故障的方法,这样做没有错。虽然,你松散多态,因为你不能像这样
// Does not work
try
{
}
catch (FaultException<IVoliationFault> ex)
{
ex.HandleException();
}
捕获你的FaultExceptions。
您(显然)也无法更改基类System.ServiceModel.FaultException<TDetail>
甚至System.ServiceModel.FaultException
以包含任何HandleException()
方法。
你可以做的是,使用反射来提取FaultException的TDetail
(如果有的话),然后使用它:
try
{
}
catch (FaultException ex)
{
var detail = ex.GetDetail<IViolationFault>(); // EDIT: Specify type
if (detail != null)
{
detail.HandleException();
}
else
{
// Either not a FaultException<TDetail>, or not FaultException<IViolationFault>.
throw;
}
}
...
public static class FaultExceptionExtensions
{
public static T GetDetail<T>(this FaultException exception)
{
if (exception == null)
throw new ArgumentNullException("exception");
Type type = exception.GetType(); // EDIT: use "exception" instead of "ex"
if (!type.IsGenericType)
{
return default(T);
}
Type genType = type.GetGenericArguments()[0];
PropertyInfo pi = type.GetProperty("Detail", genType);
Debug.Assert(pi != null, "FaultException<" + genType + ">.Detail property is missing");
object val = pi.GetValue(exception, null);
if (!typeof(T).IsInstanceOfType(val))
{
return default(T);
}
return (T)val;
}
}
答案 1 :(得分:0)
这种方法没有任何问题,它只是多态性的正常使用。
通过使所有自定义异常类派生自基本异常类而不是仅实现接口,可以减少catch块的数量。例如:
public abstract class FaultException : Exception
{
public abstract void HandleException()
}
public class Faultexception<T> : FaultException
{
public override void HandleException()
{
//your code here
}
}
通过这种方式,您可以通过以下方式捕获所有异常:
catch (FaultException ex)
{
ex.HandleException();
}
答案 2 :(得分:-1)
您可能希望了解this blog post中记录的功能方法,它允许您使try / catch逻辑更清晰/简洁。 例如:
TryCatch.Try(() =>
{
using (var stream = File.OpenRead(FileTextBox.Text))
{
Trace.WriteLine(stream.Length);
}
})
.Catch<FileNotFoundException,
DirectoryNotFoundException,
UnauthorizedAccessException>
(ex =>
{
MessageBox.Show(ex.Message, "Fail");
});