我去的選擇是在被所有的ViewModels和實體擴展一個基類明確實現IDataErrorInfo的。這似乎是讓事情與WPF結合在一起的最佳折衷辦法,並且至少將調用者隱藏的IDataErrorInfo的實現保留爲至少顯得乾淨。我公開了一個受保護的ValidateProperty,如果需要,可以在子類中覆蓋任何自定義行爲(如Password/PasswordConfirmation方案)。
public abstract class DataErrorInfo : IDataErrorInfo
{
string IDataErrorInfo.Error
{
get { return null; }
}
string IDataErrorInfo.this[string columnName]
{
get { return ValidateProperty(columnName); }
}
protected virtual string ValidateProperty(string columnName)
{
// get cached property accessors
var propertyGetters = GetPropertyGetterLookups(GetType());
if (propertyGetters.ContainsKey(columnName))
{
// read value of given property
var value = propertyGetters[columnName](this);
// run validation
var results = new List<ValidationResult>();
var vc = new ValidationContext(this, null, null) { MemberName = columnName };
Validator.TryValidateProperty(value, vc, results);
// transpose results
var errors = Array.ConvertAll(results.ToArray(), o => o.ErrorMessage);
return string.Join(Environment.NewLine, errors);
}
return string.Empty;
}
private static readonly Dictionary<string, object> PropertyLookupCache =
new Dictionary<string, object>();
private static Dictionary<string, Func<object, object>> GetPropertyGetterLookups(Type objType)
{
var key = objType.FullName ?? "";
if (!PropertyLookupCache.ContainsKey(key))
{
var o = objType.GetProperties()
.Where(p => GetValidations(p).Length != 0)
.ToDictionary(p => p.Name, CreatePropertyGetter);
PropertyLookupCache[key] = o;
return o;
}
return (Dictionary<string, Func<object, object>>)PropertyLookupCache[key];
}
private static Func<object, object> CreatePropertyGetter(PropertyInfo propertyInfo)
{
var instanceParameter = Expression.Parameter(typeof(object), "instance");
var expression = Expression.Lambda<Func<object, object>>(
Expression.ConvertChecked(
Expression.MakeMemberAccess(
Expression.ConvertChecked(instanceParameter, propertyInfo.DeclaringType),
propertyInfo),
typeof(object)),
instanceParameter);
var compiledExpression = expression.Compile();
return compiledExpression;
}
private static ValidationAttribute[] GetValidations(PropertyInfo property)
{
return (ValidationAttribute[])property.GetCustomAttributes(typeof(ValidationAttribute), true);
}
}
你是否在爲你的實體使用poco類? – dnndeveloper 2010-10-02 21:30:11
我想問哪個是這個問題的原因,在這個解決方案中,我的實體必須擴展DataErrorInfo,但是否則它們會是POCO。 – TheCodeKing 2011-08-27 23:33:42