我一直在使用表达式 - 而且我可能已经超出了我的能力 - 但是在这里......我实现了'类型安全的'INotifyPropertyChanged实现(例子是here),但是走得更远了,附带的changetracking:更改跟踪和并发 - 可以失败吗?
public abstract BaseViewModel<TEntity>:INotifyPropertyChanged
{
private readonly IBaseChangeTracker<TEntity> _changeTracker;
protected void OnPropertyChanged<T>(Expression<Func<T>> property, T value)
{
_changeTracker.AddChange(property, value);
OnPropertyChanged(property);
}
protected virtual void OnPropertyChanged<TProperty>(Expression<Func<TProperty>> property)
{
if (PropertyChanged == null) return;
PropertyChanged(this, new PropertyChangedEventArgs(property.GetMemberInfo().Name));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public abstract class BaseChangeTracker<TEntity>:IBaseChangeTracker<TEntity>
{
private readonly IDictionary<Expression, object> _changes = new Dictionary<Expression, object>();
public void AddChange<T>(Expression<Func<T>> expression, T newValue)
{
_changes.Add(expression, newValue);
}
public void ApplyChanges(TEntity entity)
{
foreach (var change in _changes)
{
var property = typeof(TEntity).GetProperty(change.Key.GetMemberInfo().Name);
property.SetValue(entity, change.Value, null);
}
}
public virtual void CopyCurrentState(TEntity entity)
{
_changes.Clear();
}
public virtual void ResetEntity(TEntity entity)
{
_changes.Clear();
}
public bool HasUnsavedChanges
{
get { return _changes.Any(); }
}
}
这似乎有点过分 - 每一个实体将拥有它,它自己的ChangeTracker保持实体的原始状态加载时,可以重置回这些,但这个想法是如果存在当它试图保存更新的实体时发生并发冲突,我从数据库重新加载实体,并通过.ApplyChanges运行它,并尝试再次保存它。这将消除我的约95%的并发问题...如果它有效。我的测试表明,对于有限的实体来说,它的工作原理就是简单的属性更改。
已知问题:
- 我还没有找到应对的集合一种优雅的方式。
我还错过了什么 - 或者我的设计中是否有明显的缺陷?
双倍回报是一个错字:-)。要首先回答你的最后一个问题 - 这些是基类 - 派生的将在setters中调用OnPropertyChanged。我同意这是一个穷人的命令堆栈实现。命令的问题在于WPF有很多内置的Ctrl-Z功能(文本框中的多级撤消等),这会混淆命令。另外,我需要能够将更改应用于除原始实体之外的其他内容(即重新加载的实体)。但是,感谢您的意见! – Goblin 2010-09-08 07:07:57
我现在将它关闭 - 感谢您的输入! :-) – Goblin 2010-09-09 20:40:36