Невозможно неявно передать лямбда-выражение как выражение

#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>> -выражения в другие типы, сначала ему нужно перейти в промежуточную переменную (или параметр).