在下面的代码片段中,我的目的是将System.Object(可以是FSharpList)转换为它所持有的任何泛型类型的列表.
match o with
| :? list<_> -> addChildList(o :?> list<_>)
| _ -> addChild(o)
Run Code Online (Sandbox Code Playgroud)
不幸的是,只有list<obj>匹配列表.我也想list<Foo>作为一个列表进行匹配.
对于某些上下文,我试图通过反射遍历对象结构,以便构建类及其子类的TreeView.考虑以下课程:
type Entity = {
Transform : Matrix
Components : obj list
Children : Entity list
}
Run Code Online (Sandbox Code Playgroud)
我想构建一个树,向我展示实体中包含的所有类.通过反射,我可以获得对象的所有属性及其值(值很重要,因为我想在列表中显示元素的Name属性,如果有的话):
let o = propertyInfo.GetValue(obj, null)
Run Code Online (Sandbox Code Playgroud)
此值可能是某种类型的列表,但值返回只是一个System.Object我在尝试将此对象转换为列表时遇到问题.我被迫做以下事情:
match o with
| :? list<obj> -> addChildList(o :?> list<obj>)
| :? list<Entity> -> addChildList(o :?> list<Entity>)
| _ -> addChild(o)
Run Code Online (Sandbox Code Playgroud)
在这里,我必须准确指定我要转换为的类型.
我真的想写这个:
match o with
| :? list<_> -> addChildList(o :?> list<_>)
| _ -> …Run Code Online (Sandbox Code Playgroud) 我正在尝试模式匹配我关心SQL生成的几种类型.理想情况下我想这样做:
let rec getSafeValue record (prop: PropertyInfo) =
match prop.GetValue(record, null) with
| :? string as str -> "'" + str + "'"
| :? Option<_> as opt ->
match opt with
| Some v -> getSafeValue v prop
| None -> "null"
| _ as v -> v.ToString()
Run Code Online (Sandbox Code Playgroud)
问题是,在这里,类型参数Option<_>获取约束以匹配,record最终只是obj.
我知道我可以做一些基于反射的检查(检查它是一个通用类型,并且它是基于名称的选项类型),但我宁愿避免这种情况,如果可能的话.
假设我有一个业务对象(没有AllowNullLiteralAttribute).
type Person(name: string) =
member val Name = name
override x.ToString() = name
Run Code Online (Sandbox Code Playgroud)
和视图模型,可选择设置所选人员.
type MainWindowModel() =
let mutable selectedPerson: Person option = None
:
member val People = ObservableCollection<Person>()
member x.SelectedPerson
with get() = selectedPerson
and set(v) =
if selectedPerson <> v then
selectedPerson <- v
x.RaisePropertyChanged("SelectedPerson")
Run Code Online (Sandbox Code Playgroud)
将WPF控件的SelectedItem属性绑定到F#选项属性(不使用AllowNullLiteralAttribute)的最佳方法是什么?
如果我这样做......
<StackPanel>
<ListBox ItemsSource="{Binding People}"
SelectedItem="{Binding SelectedPerson}"
DisplayMemberPath="Name" />
<TextBlock Text="{Binding SelectedPerson}" />
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
...导致错误,无法将'George'从类型'Person'转换为'Microsoft.FSharp.Core.FSharpOption`1 [Person]'