I have an F# exception that it is not being caught in the correct catch block.
Here’s the relevant code:
exception ConfigFileVersionIncompatabilityException of string
[<XmlType("config")>]
type Configuration() = class
let thisVersion : string = "1.0"
let mutable fileVersion : string = thisVersion
[<XmlAttribute("version")>]
member x.FileVersion
with get() = fileVersion
and set v = if v <> thisVersion
then raise (ConfigFileVersionIncompatabilityException(String.Format("Was expecting version {0} but read version {1}.", thisVersion, v)))
end
module FilterFileFunctions =
let sampleConfigFilename = "sample.filters"
let readConfig (file : string) =
try
use xmlDoc = new StreamReader(file) in
let s = XmlSerializer(typeof<Configuration>)
s.Deserialize(xmlDoc) :?> Configuration |> Success
with
| ConfigFileVersionIncompatabilityException(s) ->
String.Format("Failed to read the configuration file: \"{0}\";\nThe following reason was given:\n{1}", file, s)
|> Failure
| ex ->
String.Format("Failed to read the configuration file: \"{0}\";\n{1}", file, ex)
|> Failure
The problem is that the ex catch block catches the ConfigFileVersionIncompatabilityException exception, where it should be caught by the first block.
I tried to use :? System.Exception as ex instead of just ex and it still behaved the same.
Am I missing something?
[Edited 1 minute after initial post to remove irrelevant code.]
When an exception occurs during the deserialization, the
Deserializemethod will catch it and wrap it insideInvalidOperationException. This means that you need to chatchInvalidOperationExceptionand then analyze theInnerExceptionproperty to get to your user-defined exception.The
Data0property exposes the value carried by the exception (I used it, because you cannot access it easily in the pattern matching when using:?). However, you can avoid the ugly nesting ofmatchexpressions (and the duplication of generic handlers) using active patterns: