anchor.diff:                      sprintf "union case %O.%O has more than one field." typeof<'Union> scase.CaseInfo.Name
                       |> invalidArg "Union"
   
  -            let mkCaseEncDec encoder =
  +            let mkUnionCaseEncDec (encoder : IEncoder<'Format>) =
                   match caseField with
  -                | Some f ->
  -                    let fieldEnc, fieldDec = mkFieldEncoders f encoder
  -                    let enc u = { CaseName = label ; Payload = fieldEnc u }
  -                    let dec f =
  -                        let u = scase.CreateUninitialized()
  -                        fieldDec u f
  -
  -                    enc, dec
  +                | Some field ->
  +                    field.Accept {
  +                        new IMemberVisitor<'Union, (Func<'Union, EncodedUnion<'Format>> * Func<'Format, 'Union>)> with
  +                            member _.Visit (sfield : ShapeMember<'Union, 'Field>) =
  +                                let inline enc u =
  +                                    let f = sfield.GetByRef &u
  +                                    { CaseName = label ; Payload = encoder.Encode f }
  +
  +                                let inline dec f =
  +                                    let mutable u = scase.CreateUninitialized()
  +                                    let v = encoder.Decode f
  +                                    sfield.SetByRef(&u, v)
  +                                    u
  +
  +                                Func<_,_> enc, Func<_,_> dec
  +                    }
   
                   | None ->
  -                    let enc _ = { CaseName = label ; Payload = encoder.Empty }
  -                    let dec _ = scase.CreateUninitialized()
  -                    enc, dec
  -
  -            label, mkCaseEncDec
  +                    let inline enc _ = { CaseName = label ; Payload = encoder.Empty }
  +                    let inline dec _ = scase.CreateUninitialized()
  +                    Func<_,_> enc, Func<_,_> dec
  +
  +            label, mkUnionCaseEncDec
   
           let labels, encoderFactories =
               shape.UnionCases
  -            |> Array.map genUnionCaseEncoder
  +            |> Array.map mkUnionCaseEncoder
               |> Array.unzip
   
           let caseWithoutRecordPayload =
  
positive.code:     }
  
  /// Provides an encoder implementation for a union of events
  [<AbstractClass>]
  type UnionContractEncoder<'Union, 'Format> internal () =
      /// Gets the union case string identifier for given union instance
      abstract GetCaseName : value:'Union -> string
      /// Encodes a union instance into a decoded representation
      abstract Encode      : value:'Union -> EncodedUnion<'Format>
      /// Decodes a formatted representation into a union instance. Can potentially throw FormatException
      abstract Decode      : encodedUnion:EncodedUnion<'Format> -> 'Union
      /// Decodes a formatted representation into a union instance. Does not throw exception on format mismatches
      abstract TryDecode   : encodedUnion:EncodedUnion<'Format> -> 'Union option
  
  [<AutoOpen>]
  module private Impl =
  
negative.code:                 | _ -> false
              | _ -> false
  
          let mkUnionCaseEncoder (scase : ShapeFSharpUnionCase<'Union>) =
              // extract the case label identifier for given case
              let label =
                  scase.CaseInfo.GetCustomAttributes()
  