Как правильно реализовать свойство в F#?
Рассмотрим мою первую попытку, простой тип на F#, подобный следующему:
type Test() =
inherit BaseImplementingNotifyPropertyChangedViaOnPropertyChanged()
let mutable prop: string = null
member this.Prop
with public get() = prop
and public set value =
match value with
| _ when value = prop -> ()
| _ ->
let prop = value
this.OnPropertyChanged("Prop")
Теперь я проверяю это через C# (этот объект открыт для проекта C#, поэтому желательная семантика C# желательна):
[TestMethod]
public void TaskMaster_Test()
{
var target = new FTest();
string propName = null;
target.PropertyChanged += (s, a) => propName = a.PropertyName;
target.Prop = "newString";
Assert.AreEqual("Prop", propName);
Assert.AreEqual("newString", target.Prop);
return;
}
propName
правильно назначен, мой F# Setter работает, но второе утверждение не выполняется, потому что базовое значение prop
не изменился Этот вид имеет смысл для меня, потому что если я удаляю mutable
от prop
поле, ошибка не генерируется (и это должно быть потому, что я пытаюсь изменить значение). Я думаю, что мне не хватает фундаментальной концепции.
Как правильно перевязать / изменить prop
в Test
класс, чтобы я мог пройти мой модульный тест?
3 ответа
Попробуй это:
type Test() =
inherit BaseImplementingNotifyPropertyChangedViaOnPropertyChanged()
let mutable prop: string = null
member this.Prop
with public get() = prop
and public set value =
match value with
| _ when value = prop -> ()
| _ ->
prop <- value
this.OnPropertyChanged("Prop")
Вам нужно сделать привязку изменчивой, а затем изменить ее значение в вашем установщике. В своем исходном коде вы просто создавали новую привязку (также называемую prop
) внутри вашего сеттера, поэтому никаких изменений не было видно.
Как примечание, я бы, вероятно, использовал if .. then
вместо match
конструировать, так как это делает код более лаконичным (сопоставление паттерна особенно полезно, когда вам нужно протестировать значение с помощью нескольких сложных шаблонов). Также, public
доступ по умолчанию для member
, так что вы можете сделать код немного более кратким:
type Test() =
inherit BaseImplementingNotifyPropertyChangedViaOnPropertyChanged()
let mutable prop : string = null
member this.Prop
with get() = prop
and set(value) =
if value <> prop then
prop <- value
this.OnPropertyChanged("Prop")
В вашем паттерне вы связываете новое значение с
let prop = value
Когда вы связываете подобное значение с тем же именем, оно скрывает другое значение для области действия вновь объявленного. Я считаю, что вы действительно хотите сделать это:
prop <- value