Использование WPF сделало меня фанатом INotifyPropertyChanged. Мне нравится использовать помощник, который принимает выражение и возвращает имя в виде строки (см. Пример кода ниже). Однако во многих приложениях, которые видят очень опытные программисты, я вижу код, который обрабатывает строки raw (см. 2-й пример ниже). Под опытным я имею в виду типы MVP, которые знают, как использовать выражения.
Мне кажется, что возможность компиляции отлавливать ошибки в дополнение к простому рефакторингу делает подход Exression лучше. Есть ли аргумент в пользу использования необработанных строк, которые мне не хватает?
Ура,
Berryl
Пример помощника по выражению:
public static string GetPropertyName<T>(Expression<Func<T, object>> propertyExpression)
{
Check.RequireNotNull<object>(propertyExpression, "propertyExpression");
switch (propertyExpression.Body.NodeType)
{
case ExpressionType.MemberAccess:
return (propertyExpression.Body as MemberExpression).Member.Name;
case ExpressionType.Convert:
return ((propertyExpression.Body as UnaryExpression).Operand as MemberExpression).Member.Name;
}
var msg = string.Format("Expression NodeType: '{0}' does not refer to a property and is therefore not supported",
propertyExpression.Body.NodeType);
Check.Require(false, msg);
throw new InvalidOperationException(msg);
}
Пример кода необработанных строк (в некотором классе типов ViewModelBase):
/// <summary>
/// Warns the developer if this object does not have
/// a public property with the specified name. This
/// method does not exist in a Release build.
/// </summary>
[Conditional("DEBUG"), DebuggerStepThrough]
public void VerifyPropertyName(string propertyName) {
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] == null) {
string msg = "Invalid property name: " + propertyName;
if (ThrowOnInvalidPropertyName) throw new Exception(msg);
else Debug.Fail(msg);
}
}
/// <summary>
/// Returns whether an exception is thrown, or if a Debug.Fail() is used
/// when an invalid property name is passed to the VerifyPropertyName method.
/// The default value is false, but subclasses used by unit tests might
/// override this property's getter to return true.
/// </summary>
protected virtual bool ThrowOnInvalidPropertyName { get; private set; }