繁体   English   中英

无法推断属性获取器中的类型

[英]Cannot Infer type in property getter

我正在研究实现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); }
    }

有任何想法吗? 我看不到为什么原始代码可以推断出类型,但是我的代码却无法。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM