Решение от jpalmer показывает общую структуру, но я думаю, что есть пара проблем.У меня нет опыта работы с CSLA, поэтому я не пытался запустить его, но я скачал DLL и попытался проверить тип образца.
Прежде всего, метод RegisterProperty
не требуетлямбда-функция, но выражение (и использует ее для получения информации о свойстве с помощью отражения).Чтобы это работало, вам нужно написать помощник, используя цитаты F #:
open Microsoft.FSharp.Quotations
open System.Linq.Expressions
let prop (q:Expr<'T -> 'R>) =
match q with
| Patterns.Lambda(v, Patterns.PropertyGet(_, pi, _)) ->
let v = Expression.Variable(v.Type)
Expression.Lambda<Func<'T, 'R>>
(Expression.Property(v, pi), [v])
| _ -> failwith "wrong quotation"
Это превращает лямбда-функцию F # в кавычках в дерево выражений C # в ожидаемом формате.Затем вы можете вызвать RegisterProperty
с чем-то вроде prop <@ fun (a:Foo) -> a.Bar @>
в качестве аргумента.
Я также вижу, что IdProperty
должен быть статическим, что можно сделать с помощью static let
(если оно является приватным).Следующее должно быть правильным способом определения типа с одним свойством:
[<Serializable>]
type ResourceInfo internal (id:int, lastname:string, firstname:string) as this =
inherit ReadOnlyBase<ResourceInfo>()
// Code executed as part of the constructor
do this.Id <- id
static let IdProperty =
ReadOnlyBase<ResourceInfo>.RegisterProperty<int>
(prop <@ fun (r:ResourceInfo) -> r.Id @>)
member x.Id
with get() = x.GetProperty(IdProperty) |> unbox
and set(v) = x.LoadProperty(IdProperty, v)
Мне вообще очень нравится стиль, когда вы пишете модификаторы доступности прямо в вашем коде (как в C #), поэтому я аннотировал конструктор с помощьюinternal
как в вашем коде.Я также добавил тело конструктора, которое устанавливает свойство Id
при создании объекта.