【问题标题】:INotifyPropertyChanged on Custom DataContext Base Type doesn't fire自定义 DataContext 基类型上的 INotifyPropertyChanged 不会触发
【发布时间】:2012-04-10 17:21:53
【问题描述】:

我有一个名为MyEntityBase 的自定义基类型,用于自动生成的DataContextMyContext 中的类型的超类。在尝试创建模拟数据上下文时,我决定在 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,而entityEmployee 类型的实例,那么有什么区别呢?即使我将MyEntityBase 中的event 设置为virtual,它仍然无法正常工作。

【问题讨论】:

  • 我在这里复制了您的代码dotnetpad.net/ViewPaste/HfGdC7ypCEC4TYZ-Vb7I0A(并将虚拟添加到实体)。这似乎行得通.. 也许员工把事情搞砸了?
  • 好吧,我无法控制 Employee,因为它是使用 SQLMetal 自动生成的。但看起来区别在于缺少 override 关键字,删除它会导致它在您的测试代码中再次失败。
  • 所以看起来我需要一种方法来强制像Employee 这样的继承类始终覆盖PropertyChanged,即使关键字override 不存在。这样的事情有可能吗?

标签: linq-to-sql mocking datacontext inotifypropertychanged


【解决方案1】:

我已经实施了一个可行的解决方案,所以我会回答我自己的问题。因为我已经有一个命令行工具FindAndReplaceText.exe 用于对自动生成的MyDataContext.dbml 文件进行一些自定义,所以我只是在末尾添加了另一个调用,我将生成的MyDataContext 类中的所有事件修改为包括override。再加上让我的基类在事件定义中使用virtual,这解决了问题:

FindAndReplaceText.exe -c ^
    MyDataContext.cs ^
    "public event" ^
    "public override event"

现在属性更改在我的测试代码中正确通知。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-27
    • 1970-01-01
    • 2018-08-31
    • 1970-01-01
    相关资源
    最近更新 更多