我正在开发一个实现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); }
}
任何想法?我无法理解为什么原始代码可以推断出类型但我的代码无法推断。
答案 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
,并且会将其强制转换回属性类型而不会出错。