Этот вопрос, вероятно, потребуется время, чтобы объяснить, и мне нужно будет предоставить справочную информацию ...
Это просто то, с чем я играю и не для производства, но наВ тот момент, когда у меня есть некоторый код, который выглядит следующим образом:
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) и новое значение.Тогда я подумал, можно ли, учитывая свойство, узнать экземпляр класса, к которому оно принадлежит?