這個問題可能會需要一段時間來解釋的對象實例,我需要提供背景...獲取其中包含了指定的屬性
這只是我打得關於與和ISN」噸產品,但此刻我有一些代碼,看起來像這樣:
var myDataModel = new DataModel();
myDataModel.PropertyChanged += myDataModel_PropertyChanged;
myDataModel.ChangeProperty(t => t.TestValue, 2);
所以,而不是直接使用myDataModel.TestValue = 2
,我使用的是ChangeProperty
擴展方法,這樣我可以處理所有的變化事件並在一個地方做任何我想做的事情。我的擴展方法看起來是這樣的(是的,我知道這是哈克):
public static class NotifyPropertyChangedExtensions
{
public static void ChangeProperty<T, U>(
this T instance,
Expression<Func<T, U>> propertyToChange,
U newValue)
{
var member = propertyToChange.Body as MemberExpression;
if (member != null)
{
if (!propertyToChange.Compile().Invoke(instance).Equals(newValue))
{
var setProperty = instance.GetType().GetProperty(
member.Member.Name,
BindingFlags.SetProperty |
BindingFlags.Public |
BindingFlags.Instance);
if (setProperty != null)
{
// actually set the property
setProperty.SetValue(instance, newValue, null);
// raise the property changed event
if (typeof(INotifyPropertyChanged).IsAssignableFrom(
typeof(T)))
{
var delegatesToCall =
instance.GetType().GetField("PropertyChanged",
BindingFlags.Instance |
BindingFlags.NonPublic)
.GetValue(instance) as MulticastDelegate;
if (delegatesToCall != null)
{
var eventArgs = new PropertyChangedEventArgs(
setProperty.Name);
foreach (var @delegate in
delegatesToCall.GetInvocationList())
{
@delegate.Method.Invoke(
@delegate.Target,
new object[] { instance, eventArgs });
}
}
}
}
}
}
else
{
throw new ArgumentException(
string.Format(
"Cannot determine the property to change {0}",
propertyToChange));
}
}
}
在此架構下,我的數據模型是相當乾淨:
public class DataModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int TestValue { get; set; }
}
也就是說,我可以使用自動屬性,而不必擔心引發事件等
現在,我真正想要做的是更接近於這樣的:
var dataModel = new DataModel();
myDataModel.PropertyChanged += myDataModel_PropertyChanged;
myDataModel.TestValue.Set(2); // this is what I want...
所以,我想我基本上需要一個擴展方法 - 但我只能看到如何發送屬性本身(在這種情況下是TestValue)和新的值。那麼我想知道給定一個屬性是否有可能找到它所屬類的實例?
Tbh我不會這樣做。您正在推動將PropertyChanged事件從類中正確提升到其用戶的責任。這打破了封裝原則。該類應確保它的行爲與預期相同,而不是使用它的代碼。 – dtb 2010-07-31 13:39:37
@dtb:這是一個「是否有可能」的問題,我不會把這個附近的生產代碼... – 2010-07-31 13:44:49
而不是'var setProperty = instance.GetType()。GetProperty(...)',它依賴於財產*名稱*,您應該可以從propertyToChange獲得財產。例如,在你的代碼中,'(PropertyInfo)member.Member'就可以做到。 – Timwi 2010-07-31 14:13:53