#c# #lambda
#c# #лямбда
Вопрос:
Я пытаюсь написать вспомогательный класс, который, учитывая объект типа INotifyPropertyChanged
, может помочь вам проверить, что данное изменение свойства действительно вызвало PropertyChanged
событие. Это шаблон, которому мы регулярно следуем, поэтому я создал следующий класс, чтобы помочь в написании модульных тестов:
public class PropertyChangeHelper<TClass, TProperty> where TClass : class, INotifyPropertyChanged
{
#region Fields
private readonly TClass _model;
private readonly string _propertyName;
private readonly Action<TProperty> _setter;
#endregion Fields
#region Properties
public bool ChangeEventFired { get; private set; }
#endregion Properties
#region Construction
public PropertyChangeHelper(TClass model, Expression<Func<TClass, TProperty>> property)
{
_model = model ?? throw new ArgumentNullException(nameof(model));
if (!(property.Body is PropertyExpression propertyExpression))
throw new ArgumentException("The given expression must be for a property, i.e., with { get; set; }.", nameof(property));
_propertyName = propertyExpression.PropertyInfo.Name;
_setter = targetValue => propertyExpression.PropertyInfo.SetValue(_model, targetValue);
}
~PropertyChangeHelper() => _model.PropertyChanged -= RecordPropertyChange;
#endregion Construction
#region Methods
/// <summary>
/// Updates the property's value to the given target value.
/// </summary>
public void UpdateProperty(TProperty targetValue) => _setter.Invoke(targetValue);
private void RecordPropertyChange(object _, PropertyChangedEventArgs args)
{
if (args.PropertyName == _propertyName)
ChangeEventFired = true;
}
#endregion Methods
}
Идея состоит в том, чтобы иметь возможность передавать объект (обычно виртуальную машину) и лямбда-выражение, чтобы указать рассматриваемое свойство, а затем указать ему обновить значение и проверить, что событие сработало (или не сработало, если значение было одинаковым). Модульный тест может выглядеть примерно так:
[Test]
public void Test()
{
var vm = new VM();
var helper = new PropertyChangeHelper<VM, int>(vm, x => x.SomeIntProperty);
helper.UpdateProperty(5);
Assert.IsTrue(helper.ChangeEventFired);
}
Однако проблема, с которой я сталкиваюсь, заключается в том, что я получаю сообщение об ошибке для Expression
параметра, в котором указано, что «Тип аргумента «лямбда-выражение» не может быть присвоен типу параметра FastExpressionCompiler.LightExpression.Expression<System.Func<VM, int>>
.
Я видел то же самое, что и в других библиотеках, таких как Moq, поэтому я не понимаю, почему это не работает. Может ли кто-нибудь пролить свет на то, что компилятору в этом не нравится?
Комментарии:
1. Получение ошибки в какой строке предоставленного кода?
2. Пятая строка второго фрагмента:
var helper = new PropertyChangeHelper<VM, int>(vm, x => x.SomeIntProperty);
3. Проверьте, есть ли у вас «использование статического FastExpressionCompiler. LightExpression. Выражение» в вашем файле и, если да, удалите его.
4.Я согласен, вам нужно будет использовать
System.Linq.Expressions.Expression<Func<TClass, TProperty>>
вместо этого. Вы всегда можете преобразовать егоFastExpression
в конструктор, если вам нужно5. Затем полностью укажите тип параметра в конструкторе. Компилятор не сразу выполняет преобразование из вашего лямбда
System.Linq.Expressions.Expression<Func<TClass, TProperty>>
-выражения в другие типы, сначала ему нужно перейти в промежуточную переменную (или параметр).