无法在属性getter中输入

时间:2016-08-29 20:37:58

标签: c# wpf mvvm

我正在开发一个实现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)&#39;无法从使用中推断出来。尝试明确指定类型参数。

所以我必须这样实现它:

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

任何想法?我无法理解为什么原始代码可以推断出类型但我的代码无法推断。

1 个答案:

答案 0 :(得分:1)

您可以使--- title: "Untitled" author: "Author" date: "8/29/2016" output: html_document runtime: shiny --- ```{r} set.seed(12345) library(plyr) library(dplyr) dt <- data.frame(a=1:10, b=sample(1:3, 10, replace=T)) formula <- parse(text=paste0("a", "+1"))[[1]] #this does work in R, but not in markdown res <- dt %>% ddply(.(b), transform, diff = eval(formula)) res ``` 的返回类型为GetValue,并且会将其强制转换回属性类型而不会出错。

相关问题