不能在属性getter中推断类型

本文关键字:类型 getter 属性 不能 | 更新日期: 2023-09-27 18:04:32

我正在研究一个可绑定的基类,它实现了INotifyPropertyChanged和IDataErrorInfo,这样我就可以编写带有更改通知绑定到WPF的属性,并允许我使用DataAnnotations验证。

这篇文章值得称赞:https://code.msdn.microsoft.com/windowsdesktop/Validation-in-MVVM-using-12dafef3我无耻地抄袭了这篇文章

虽然这篇文章很好,但它没有利用CallerMemberName,所以我试图清理一些东西。

示例作者所做的一件有趣的事情是编写SetValue和GetValue方法,它们将所有私有属性值存储在字典中,这允许您跳过将属性值存储在类的私有字段中。作者使用了四个函数来做到这一点:

    /// <summary>
    /// Sets the value of a property.
    /// </summary>
    /// <typeparam name="T">The type of the property value.</typeparam>
    /// <param name="propertySelector">Expression tree contains the property definition.</param>
    /// <param name="value">The property value.</param>
    protected void SetValue<T>(Expression<Func<T>> propertySelector, T value)
    {
        string propertyName = GetPropertyName(propertySelector);
        SetValue<T>(propertyName, value);
    }
    /// <summary>
    /// Sets the value of a property.
    /// </summary>
    /// <typeparam name="T">The type of the property value.</typeparam>
    /// <param name="propertyName">The name of the property.</param>
    /// <param name="value">The property value.</param>
    protected void SetValue<T>(string propertyName, T value)
    {
        if (string.IsNullOrEmpty(propertyName))
        {
            throw new ArgumentException("Invalid property name", propertyName);
        }
        _values[propertyName] = value;
        NotifyPropertyChanged(propertyName);
    }
    /// <summary>
    /// Gets the value of a property.
    /// </summary>
    /// <typeparam name="T">The type of the property value.</typeparam>
    /// <param name="propertySelector">Expression tree contains the property definition.</param>
    /// <returns>The value of the property or default value if not exist.</returns>
    protected T GetValue<T>(Expression<Func<T>> propertySelector)
    {
        string propertyName = GetPropertyName(propertySelector);
        return GetValue<T>(propertyName);
    }
    /// <summary>
    /// Gets the value of a property.
    /// </summary>
    /// <typeparam name="T">The type of the property value.</typeparam>
    /// <param name="propertyName">The name of the property.</param>
    /// <returns>The value of the property or default value if not exist.</returns>
    protected T GetValue<T>(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName))
        {
            throw new ArgumentException("Invalid property name", propertyName);
        }
        object value;
        if (!_values.TryGetValue(propertyName, out value))
        {
            value = default(T);
            _values.Add(propertyName, value);
        }
        return (T)value;
    }

我用下面两个函数代替了这四个函数:

    /// <summary>
    /// Sets the value of a property.
    /// </summary>
    /// <typeparam name="T">The type of the property value.</typeparam>
    /// <param name="propertyName">The name of the property.</param>
    /// <param name="value">The property value.</param>
    protected void SetValue<T>(T value, [CallerMemberName] string propertyName = "")
    {
        if (string.IsNullOrEmpty(propertyName))
        {
            throw new ArgumentException("Invalid property name", propertyName);
        }
        _values[propertyName] = value;
        NotifyPropertyChanged(propertyName);
    }
    /// <summary>
    /// Gets the value of a property.
    /// </summary>
    /// <typeparam name="T">The type of the property value.</typeparam>
    /// <param name="propertyName">The name of the property.</param>
    /// <returns>The value of the property or default value if not exist.</returns>
    protected T GetValue<T>([CallerMemberName] string propertyName = "")
    {
        if (string.IsNullOrEmpty(propertyName))
        {
            throw new ArgumentException("Invalid property name", propertyName);
        }
        object value;
        if (!_values.TryGetValue(propertyName, out value))
        {
            value = default(T);
            _values.Add(propertyName, value);
        }
        return (T)value;
    }

我认为这是一个改进,因为它消除了一些函数并简化了调用方法。

使用原始函数的属性实现如下:

    [Range(1, 100, ErrorMessage = "Age should be between 1 to 100")]
    public int Age
    {
        get { return GetValue(() => Age); }
        set { SetValue(() => Age, value); }
    }

我想在我的中实现相同的属性,如下所示:

    [Range(1, 100, ErrorMessage = "Age should be between 1 to 100")]
    public int Age
    {
        get { return GetValue(); }
        set { SetValue(value); }
    }

唯一的问题是GetValue给了我错误:

方法____ . getvalue (string)'的类型参数不能从用法中推断出来。尝试显式指定类型参数。

所以我必须这样实现它:

    [Range(1, 100, ErrorMessage = "Age should be between 1 to 100")]
    public int Age
    {
        get { return GetValue<int>(); }
        set { SetValue(value); }
    }

任何想法?我不明白为什么原来的代码可以推断类型,而我的代码不能。

不能在属性getter中推断类型

您可以将GetValue的返回类型设置为dynamic,并且它将被强制返回到属性类型而不会出现错误