【发布时间】:2013-01-31 08:31:39
【问题描述】:
鉴于以下简单的控制台应用程序,它说明了通知更改属性的两种方式:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var person = new Person(){ Name = "Me" };
person.Age = 20;
person.Weight = 80.5F;
person.RandomProperty = new RandomComplexObject();
Console.ReadKey();
}
}
public class Person : BaseObject
{
public string Name
{
get { return _name; }
set { SetProperty(ref value, ref _name, false); }
}
public int Age
{
get { return _age; }
set { SetProperty<int>(ref value, ref _age, true, "Age", "Weight"); }
}
public float Weight
{
get { return _weight; }
set { SetProperty(ref value, ref _weight, true, () => Weight, () => Age); }
}
public RandomComplexObject RandomProperty
{
get { return _rco; }
//*** the following line has the error:
//-------------------------------------
set { SetProperty(ref value, ref _rco, true, () => Name, () => Age, () => Weight); }
}
private float _weight;
private int _age;
private string _name;
private RandomComplexObject _rco;
}
public class BaseObject : INotifyPropertyChanged
{
protected void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
var handler = PropertyChanged;
if (handler != null)
{
var body = propertyExpression.Body as MemberExpression;
var expression = body.Expression as ConstantExpression;
handler(expression.Value, new PropertyChangedEventArgs(body.Member.Name));
}
}
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler == null)
return;
handler(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<T>(ref T newValue, ref T currentValue, bool notify, params string[] notifications)
{
if (EqualityComparer<T>.Default.Equals(newValue, currentValue))
return false;
currentValue = newValue;
if (notify)
foreach (var propertyName in notifications)
OnPropertyChanged(propertyName);
return true;
}
protected bool SetProperty<T, TProperty>(ref T newValue, ref T currentValue, bool notify, params Expression<Func<TProperty>>[] notifications)
{
if (EqualityComparer<T>.Default.Equals(newValue, currentValue))
return false;
currentValue = newValue;
if (notify)
foreach (var notification in notifications)
OnPropertyChanged(notification);
return true;
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class RandomComplexObject{}
}
在方法调用SetProperty(ref value, ref _rco, true, () => Name, () => Age, () => Weight);就行了我遇到编译错误:
无法将 lambda 表达式转换为类型“字符串”,因为它不是委托类型
IDE中直接显示的错误是:
无法从用法中推断方法“bool ConsoleApplication1.BaseObject.SetProperty(ref T, ref T, bool, params Expression
>[])”的类型参数。尝试明确指定类型参数。
如何消除对SetProperty() 方法的调用的歧义?有没有更简洁的语法写法?
【问题讨论】:
-
你到底想用这个设计完成什么?
-
@RoyDictus 这是为了提供一个选项,开发人员可以避免在属性通知中使用魔术字符串。在
SetProperty()调用中传递单个 lambda 是微不足道的,但我希望选择通知多个属性。不幸的是,删除采用params string[]的SetProperty()将涉及合理数量的更改 - 我宁愿调用代码随着文件的接触而逐步更改。 -
在属性的设置器中,您指的是多个不相关的属性。这是一个糟糕的设计。如果您想要属性更改通知,在字符串中硬编码属性名称并不是那么糟糕——它不是 100% 干净的,但至少它比上面代码中的方法干净得多。我会坚持使用通知属性更改的标准方式msdn.microsoft.com/en-us/library/ms743695.aspx。万事如意!
标签: c# generics inotifypropertychanged disambiguation