I have a WPF project and am struggling to figure out how to have two separate files:
ViewModelBase
ViewModel
When I put the classes in their own file, I receive a compile error for the viewModel because the ViewModelBase cannot be found.
Also, I am using a WPF project. As a result, I am unable to move files within Solution Explorer up and down based on file dependencies.
The code is below:
module MVVM
open System.ComponentModel
open Microsoft.FSharp.Quotations.Patterns
type ViewModelBase () =
let propertyChanged =
Event<PropertyChangedEventHandler,PropertyChangedEventArgs>()
let getPropertyName = function
| PropertyGet(_,pi,_) -> pi.Name
| _ -> invalidOp "Expecting property getter expression"
interface INotifyPropertyChanged with
[<CLIEvent>]
member this.PropertyChanged = propertyChanged.Publish
member private this.NotifyPropertyChanged propertyName =
propertyChanged.Trigger(this,PropertyChangedEventArgs(propertyName))
member this.NotifyPropertyChanged quotation =
quotation |> getPropertyName |> this.NotifyPropertyChanged
type ViewModel() =
inherit ViewModelBase()
let mutable firstName = ""
let mutable lastName = ""
member this.FirstName
with get() = firstName
and set(value) =
firstName <- value
base.NotifyPropertyChanged(<# this.FirstName #>)
member this.LastName
with get() = lastName
and set(value) =
lastName <- value
base.NotifyPropertyChanged(<# this.LastName #>)
member this.GetFullName() =
sprintf "%s %s" (this.FirstName) (this.LastName)
Any ideas on how I can compile this simple WPF project with a class per file?
Related
I'm working on a new system where I am using strongly typed Id values for my entities. To do that, I've followed a pattern that I've seen recommended before. The code seems very repetitive though and I'd like to simplify it.
type PersonId = private PersonId of string
module PersonId =
let private prefix = "person"
let value (PersonId id) = id
let create (id: string) = PersonId(sprintf "%s_%s" prefix id)
type OrderId = private OrderId of string
module OrderId =
let private prefix = "order"
let value (OrderId id) = id
let create (id: string) = OrderId(sprintf "%s_%s" prefix id)
Is there a way to make this code more generic so I don't have to repeat the module code? I was thinking of making an EntityId discriminated union of the PersonId and OrderId type, but not sure what the EntityId module code might look like. Thanks for the help.
I think you're headed towards something like this:
type EntityId =
private
| PersonId of string
| OrderId of string
module EntityId =
let init makeEntity prefix =
fun id -> makeEntity (sprintf "%s_%s" prefix id)
let value = function
| PersonId id
| OrderId id -> id
The trick here is that the init function is used to make your current create functions, like this:
module PersonId =
let create = EntityId.init PersonId "person"
module OrderId =
let create = EntityId.init OrderId "order"
And then you can use it like this:
let personId = PersonId.create "abc"
let orderId = OrderId.create "xyz"
printfn "%A" personId
printfn "%A" orderId
printfn "%s" <| EntityId.value personId
printfn "%s" <| EntityId.value orderId
Output is:
PersonId person_abc
OrderId order_xyz
person_abc
order_xyz
P.S. If you like currying, you can simplify init to:
let init makeEntity prefix id =
makeEntity (sprintf "%s_%s" prefix id)
I'm running across an issue when I define a field of option type while serializing for JSON.
Before works (without option)
[<DataContract>]
type Article = {
[<field: DataMemberAttribute(Name="version") >]
version: string
}
After throws error (with option)
[<DataContract>]
type Article = {
[<field: DataMemberAttribute(Name="version") >]
version: string option
}
method threw exception:
System.Runtime.Serialization.SerializationException: Expecting state 'Element'.. Encountered 'Text' with name '', namespace ''.
Related Code
let response = request.GetResponse() :?> HttpWebResponse
use reader = new StreamReader(response.GetResponseStream())
use memoryStream = new MemoryStream(ASCIIEncoding.Default.GetBytes(reader.ReadToEnd()))
let result = (new DataContractJsonSerializer(typeof<Article>)).ReadObject(memoryStream) :?> Article
Here is a definition with a nullable int. String can already be null to which the zillions of Null reference exceptions attest...
open System
[<DataContract>]
type Person2 = {
[<DataMember(Name="Name") >]
entityName: Nullable<int>
[<DataMember(Name="Type") >]
entityType: String
}
However if you plan to fill this with a bunch of nulls maybe you should consider a class. This is really horrible but here's how it looks:
let p1 = { entityName = Nullable(10); entityType = "John"}
let p2 = { entityName = System.Nullable(); entityType = null}
val p1 : Person2 = {entityName = 10;
entityType = "John";}
val p2 : Person2 = {entityName = null;
entityType = null;}
Using F#, I had the following (simplified), which works fine:
type MyInt =
struct
val Value: int
new v = { Value = v }
end
static member inline name() = "my_int" // relevant line
let inline getName (tp: ^a): string = (^a: (static member name : unit -> string) ())
It seems to me that the statically resolved member signature from the explicit member constraint requires a function. I was wondering if it can also be used with a field instead. I tried a few things:
The following will compile, but won't work and will fail with the error
error FS0001: The type 'MyInt' does not support the operator 'get_name'
type MyInt =
//...
static member inline name = "my_int"
let inline getName (tp: ^a): string = (^a: (static member name : string) ())
Removing the () to prevent it from trying to call the gettor is a syntax error. If I change it to actually implement the gettor, it works (but that's essentially the same as the original code).
type MyInt =
// ...
static member inline name with get() = "my_int"
let inline getName (tp: ^a): string = (^a: (static member name : string) ())
Is there a way to get, using explicit member constraints or similar means, the compiler to find the static field? Or is this simply a limitation of the syntax of constraints?
Update:
Surprisingly, it does work with instance fields, or as in this case, struct fields: using (^a: (member Value: 'b) ()), which will call the member Value.
I define a property in a class like:
type Customer() =
let mutable _lastName = String.Empty
member val LastName = _lastName with get
And in the method QueryData I assign a value to _lastName:
member self.QueryData () =
// CODE
let addressData = bp.GetStructure("PE_PERSONALDATA")
_lastName <- addressData.GetString("LASTNAME")
null
| RfcCommunication ex ->
let basedComm = ex :> Exception
basedComm
| RfcLogon ex ->
let basedLogon = ex :> Exception
basedLogon
| RfcAbapRuntime ex ->
let basedAbap = ex :> Exception
basedAbap
In the main function I created an instance of Customer() and read the LastName property:
[<EntryPoint>]
let main argv =
let customer = CustomerBapi.Customer()
let ex = customer.QueryData()
if ex <> null then printfn "%s" ex.Message
printfn "%s" customer.LastName
The result is empty string. I tried to debug the program and see that _lastName is not empty
Why is the LastName property is empty?
Your property should look like this:
member this.LastName with get () = _lastName
The type of property you are using is passing _lastName as the value to initialise it with.
Explanation from MSDN:
Private values that hold the data for properties are called backing
stores. To have the compiler create the backing store automatically,
use the keywords member val, omit the self-identifier, then provide an
expression to initialize the property. If the property is to be
mutable, include with get, set. For example, the following class type
includes two automatically implemented properties. Property1 is
read-only and is initialized to the argument provided to the primary
constructor, and Property2 is a settable property initialized to an
empty string:
type MyClass(property1 : int) =
member val Property1 = property1
member val Property2 = "" with get, set
I'm writing a generic class that has two constructors: the first one initializes every field, the second (parameter-less) should not initialize anything.
The only way I found to achieve this is calling the main constructor with "empty" arguments, i.e. Guid.Empty and null. Besides not looking good functional style to my untrained eyes, this means that I have to put a a' : null constraint on the second parameter, which I don't want:
type Container<'a when 'a : null>(id : Guid, content : 'a) =
let mutable _id = id
let mutable _content = content
new() = Container<'a>(Guid.Empty, null)
member this.Id
with get() = _id
and set(value) = _id <- value
member this.Content
with get() = _content
and set(value) = _content <- value
I see two ways to solve this:
use something like the default c# keyword instead of null (does such a thing exist in F#?)
use a different syntax to specify constructors and private fields (how?)
What is the best way to implement this class?
The F# analog to default is Unchecked.default<_>. It is also possible to use explicit fields which you don't initialize:
type Container<'a>() =
[<DefaultValue>]
val mutable _id : Guid
[<DefaultValue>]
val mutable _content : 'a
new (id, content) as this =
new Container<'a>() then
this._id <- id
this._content <- content
However, in general, your overall approach is somewhat unidiomatic for F#. Typically you'd use a simple record type (perhaps with a static method to create uninitialized containers, although this seems to have questionable benefit):
type 'a Container = { mutable id : Guid; mutable content : 'a } with
static member CreateEmpty() = { id = Guid.Empty; content = Unchecked.defaultof<_> }
In many situations, you could even use an immutable record type, and then use record update statements to generate new records with updated values:
type 'a Container = { id : Guid; content : 'a }
[<GeneralizableValue>]
let emptyContainer<'a> : 'a Container =
{ id = Guid.Empty;
content = Unchecked.defaultof<_> }
let someOtherContainer = { emptyContainer with content = 12 }
If the type will be used from languages other than F#, the following provides a natural interface in F#, and C#, for example.
type Container<'a>(?id : Guid, ?content : 'a) =
let orDefault value = defaultArg value Unchecked.defaultof<_>
let mutable _id = id |> orDefault
let mutable _content = content |> orDefault
new() = Container(?id = None, ?content = None)
new(id : Guid, content : 'a) = Container<_>(?id = Some id, ?content = Some content)
member this.Id
with get() = _id
and set(value) = _id <- value
member this.Content
with get() = _content
and set(value) = _content <- value
If it will only be used from F#, you can omit the following constructor overloads
new(id : Guid, content : 'a) = Container<_>(?id = Some id, ?content = Some content)
new() = Container()
because the overload accepting optional args handles both these cases equally well in F#.