【发布时间】:2012-04-10 17:21:53
【问题描述】:
我有一个名为MyEntityBase 的自定义基类型,用于自动生成的DataContext 类MyContext 中的类型的超类。在尝试创建模拟数据上下文时,我决定在 MyEntityBase 上实现 INotifyPropertyChanged,这样我就可以一般地跟踪更改。
这是我的班级的样子:
public abstract class MyEntityBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
}
基于这个类,我创建了一个通用的Repository<T> 类,用于存储特定类型实体的实例。此类背后的基本思想是提供类似于数据上下文的方法,但由内存列表支持。我还想模拟跟踪更改,因为更改集对于我们的应用程序的业务逻辑很重要,以便与 3rd 方系统同步。
这是Repository<T>的基本shell实现:
public class Repository<T>
where T : MyEntityBase, INotifyPropertyChanged
{
protected List<T> _data;
public Repository(List<T> data)
{
this._data = data;
foreach (var entity in this._data)
{
entity.PropertyChanged += new PropertyChangedEventHandler(entity_PropertyChanged);
}
}
protected void entity_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Console.WriteLine("HERE");
}
}
现在我创建一个Employee 类型的简单存储库,填充一些数据,并尝试修改数据的属性。我希望PropertyChanged 事件被引发,因为Employee 对象具有来自自动生成的DataContext 的内置属性更改通知。但是,当我运行以下代码时,在任何地方的输出中都看不到HERE:
var data = new List<Employee> {
new Employee { FirstName = "Bob" },
new Employee { FirstName = "Joe" },
};
var repo = new Repository<Employee>(data);
// This should fire the PropertyChanged event
data[0].FirstName = "John";
我做错了什么?
更新:如果我将订阅事件的行更改为以下内容:
(entity as Employee).PropertyChanged += ...
然后它工作正常。但是,T 已知为Employee,而entity 是Employee 类型的实例,那么有什么区别呢?即使我将MyEntityBase 中的event 设置为virtual,它仍然无法正常工作。
【问题讨论】:
-
我在这里复制了您的代码dotnetpad.net/ViewPaste/HfGdC7ypCEC4TYZ-Vb7I0A(并将虚拟添加到实体)。这似乎行得通.. 也许员工把事情搞砸了?
-
好吧,我无法控制
Employee,因为它是使用SQLMetal自动生成的。但看起来区别在于缺少override关键字,删除它会导致它在您的测试代码中再次失败。 -
所以看起来我需要一种方法来强制像
Employee这样的继承类始终覆盖PropertyChanged,即使关键字override不存在。这样的事情有可能吗?
标签: linq-to-sql mocking datacontext inotifypropertychanged