不能在属性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); }
}
任何想法?我不明白为什么原来的代码可以推断类型,而我的代码不能。
您可以将GetValue
的返回类型设置为dynamic
,并且它将被强制返回到属性类型而不会出现错误