ingted
ingted

Reputation: 3

F# type extensions property not works

It is weird that extended property is not mutable... Could any one help?

open System.IO.Ports
open System.Text
open System.Text.RegularExpressions

type UAgent<'T> = MailboxProcessor<'T>


module ComPortManager =
    type MailboxProcessor<'T> with
        member this.sP = ref(new SerialPort("0"))
        member this.receivedSeq : byte [] = Array.empty
        member this.pastMsgSent : seq<string> = Seq.empty

    type Cmd =
    | Send = 0
    | Remove = 1
    | Add = 2


    type UartOP =
    | Open of unit
    | Comm of Cmd * string
    | Handler of Cmd * SerialDataReceivedEventHandler


    let CreateComPort = 
        fun pN bR (p : System.IO.Ports.Parity) dB (sB : System.IO.Ports.StopBits) to' handler ->
            match Array.exists (fun a -> a = pN) (SerialPort.GetPortNames()) with
            | false -> failwith "Not valid comport!"
            | _ -> ()            

            let mutable agent : UAgent<UartOP> =
                UAgent.Start(handler)
            let mutable sP = new SerialPort(pN)
            agent.sP := sP
            agent.sP.contents.Close()
            match agent.sP.contents <> null with
            | true ->
                agent.sP.contents.Close() 
            | false ->
                ()

            agent.sP.contents.BaudRate    <- bR
            printfn "\r\n=o==> %s" (bR.ToString())
            printfn "\r\n=o==> %s" (sP.BaudRate.ToString())
            printfn "\r\n=o==> %s" (agent.sP.contents.BaudRate.ToString())
            agent.sP.contents.Parity      <- p
            agent.sP.contents.DataBits    <- dB
            agent.sP.contents.StopBits    <- sB
            agent.sP.contents.ReadTimeout <- to'             
            agent

The baud rate of property contents of variable sP doesn't change after trying to set it to bR...

The output looks like this:

=o==> 19200

=o==> 9600

=o==> 9600

Upvotes: 0

Views: 69

Answers (1)

Tomas Petricek
Tomas Petricek

Reputation: 243041

The way you're trying to do this is not going to work. In F#, extensions cannot add new fields to existing types, and so you cannot really add additional mutable state.

What your definition is doing is that it is adding a bunch of read-only properties that are always returning a new value (a new reference cell in case of sP or a new array in case of receivedSeq). Every time you call agent.sP, it creates a new value and returns it (so you end up mutating new copies that are immediately garbage collected).

To solve this, you'll need to create a new type that wraps a mailbox processor and adds the additional state, something along those lines:

type MyMailbox<'T>() = 
  let mbox = MailboxProcessor.Start( ... )
  member val sP = ref(new SerialPort("0")) with get, set
  member val receivedSeq : byte [] = Array.empty with get

Upvotes: 3

Related Questions