【问题标题】:Override base class methods in derived class and fire its event覆盖派生类中的基类方法并触发其事件
【发布时间】:2017-02-06 07:36:56
【问题描述】:

我想在派生类中重写基类方法,然后在派生类中做一些事情。因此基类方法使用其泛型类型调用。然后我的目标是触发被覆盖的派生类方法。

我有以下代码:

    public class Service<T> : Interface.IService<T> where T : class
    {

    public virtual event System.EventHandler<EntitySavingEventArgs<T>> BeforeSavingRecord;

    public Service()
    {

    }

    public virtual void OnBeforeSavingRecord(object sender, EntitySavingEventArgs<T> e)
    {

    }

    private readonly DbContext _dbContext;
    public Service(DbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public virtual void Create(T item)
    {
        if (item == null)
            throw new ArgumentNullException("item");

        BeforeSavingRecord?.Invoke(this, new EntitySavingEventArgs<T>() { SavedEntity = item });
        _dbContext.Set(typeof(T)).Add(item);
        _dbContext.SaveChanges();
    }
}

在它的派生类中我有这样的东西:

[Service]
public partial class BankBusiness : Service<Bank>, IBankBusiness
{
    public BankBusiness()
        : base(ContainerManager.Container.Resolve<MyContext>())
    {

    }


    public override void OnBeforeSavingRecord(object sender, EntitySavingEventArgs<Bank> e)
    {
        //Do something with entity item before saving
        base.OnBeforeSavingRecord(sender, e);
    }
}

然后在我调用时在我的控制器中

bankBiz.Create(new Bank() { ... });

我想触发注册到 BeforeSavingRecord 事件的 bankBiz(派生类)重写方法 (OnBeforeSavingRecord)。

我不知道我的方案是否正确,以及我如何才能触发它。

如果不正确,我应该怎么做。

【问题讨论】:

  • 这行:BeforeSavingRecord?.Invoke(this, new EntitySavingEventArgs&lt;T&gt;() { SavedEntity = item }); 不会导致事件触发吗?
  • 确实如此。但我不想在派生类中调用它。我想通过覆盖做一些事情,调用被覆盖的方法。
  • 那我真的不明白你。你写道:“然后我的目标是触发被覆盖的派生类方法。”我在您发布的代码中看到的唯一被覆盖的方法是public override void OnBeforeSavingRecord
  • 在方法Create 中调用OnBeforeSavingRecord 如果您从派生类的实例调用它,将首先执行派生类的重写方法中的代码。请查看我的 edfit
  • 谢谢伙计。您的解决方案有效,但在我的情况下无效。请查看我的上一篇文章

标签: c# event-handling overriding


【解决方案1】:

我在基类中实现了一个类似的模式,我是这样做的:

基地:

public virtual void OnBeforeSavingRecord(object sender, EntitySavingEventArgs<T> e)
{    }

在派生类中,我有你使用的调用:

派生:

public override void OnBeforeSavingRecord(object sender, EntitySavingEventArgs<Bank> e)
{
    //Do something with entity item before saving
    base.OnBeforeSavingRecord(sender, e);
}

在我的情况下,要触发事件,只需调用就足够了

OnBeforeSavingRecord(this, new EntitySavingEventArgs<T>() { SavedEntity = item });

整个场景对我有用。

编辑:

如果从派生类的实例调用OnBeforeSavingRecord,将执行派生类的重写方法中的代码!

如果我理解正确,您希望在方法Create 中触发事件,但希望执行派生类的事件代码。如果事件被覆盖,就像你的情况一样。您可以使用这个简单的控制台应用程序对其进行测试:(只需复制粘贴并运行)

public class Service 
{
    public virtual event System.EventHandler<EventArgs> BeforeSavingRecord;

    public virtual void OnBeforeSavingRecord(object sender, EventArgs e)
    {
        Console.WriteLine("Base: OnBeforeSavingRecord method call");
    }

    public virtual void Create(object item)
    {
        Console.WriteLine("Base: Create method call");
        // this will call the method of the derived class! if you call it from an instance of the derived class
        OnBeforeSavingRecord(this, new EventArgs());
    }
}

public partial class BankBusiness : Service
{
    public override void OnBeforeSavingRecord(object sender, EventArgs e)
    {
        //Do something with entity item before saving
        Console.WriteLine("Derived Class OnBeforeSavingRecord CALL");

        base.OnBeforeSavingRecord(sender, e);                
    }
}

static void Main(string[] args)
{        
    BankBusiness bankBiz = new BankBusiness();

    bankBiz.Create(new object());

    Console.ReadKey();
}

【讨论】:

  • 我不想在我的派生类中调用 OnBeforeSavingRecord。我想采取一种方法,在我的派生类中只使用重写的方法,并在我使用 Create 方法时调用基类
【解决方案2】:

@Mong Zhu 您的解决方案有效,但不适用于我的场景。我想出了以下解决方案

public class Service<T> : Interface.IService<T> where T : class
{

    Interface.IService<T> implementation;

    public virtual event System.EventHandler<EntitySavingEventArgs<T>> BeforeSavingRecord;

    public virtual event System.EventHandler<EntitySavingEventArgs<T>> SavingRecord;

    public virtual event System.EventHandler<EntitySavingEventArgs<T>> RecordSaved;

    public void PopulateEvents(Interface.IService<T> _implementation)
    {
        implementation = _implementation;

        implementation.BeforeSavingRecord += new System.EventHandler<EntitySavingEventArgs<T>>(this.OnBeforeSavingRecord);
        implementation.SavingRecord += new System.EventHandler<EntitySavingEventArgs<T>>(this.OnSavingRecord);
        implementation.RecordSaved += new System.EventHandler<EntitySavingEventArgs<T>>(this.OnRecordSaved);
    }

    public virtual void OnBeforeSavingRecord(object sender, EntitySavingEventArgs<T> e)
    {

    }

    public virtual void OnSavingRecord(object sender, EntitySavingEventArgs<T> e)
    {

    }
    public virtual void OnRecordSaved(object sender, EntitySavingEventArgs<T> e)
    {

    }

    private readonly DbContext _dbContext;
    public Service(DbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public virtual void Create(T item)
    {

        if (item == null)
            throw new ArgumentNullException("item");

        BeforeSavingRecord?.Invoke(this, new EntitySavingEventArgs<T>() { SavedEntity = item });
        _dbContext.Set(typeof(T)).Add(item);
        SavingRecord?.Invoke(this, new EntitySavingEventArgs<T>() { SavedEntity = item });
        _dbContext.SaveChanges();
        RecordSaved?.Invoke(this, new EntitySavingEventArgs<T>() { SavedEntity = item });

    }
}

和派生类:

    [Service]
public partial class BankBusiness : Service<Bank>, IBankBusiness
{
    public BankBusiness()
        : base(ContainerManager.Container.Resolve<MyContext>())
    {
        base.PopulateEvents(this);
    }


    public override void OnBeforeSavingRecord(object sender, EntitySavingEventArgs<Bank> e)
    {

        base.OnBeforeSavingRecord(sender, e);
    }
}

重点在哪里

base.PopulateEvents(this);

【讨论】:

  • 我仍然没有真正明白你的要求。您错过了必须注册活动的地方?
  • 您能解释一下使用 BeforeSavingRecord?.Invoke(this...OnBeforeSavingRecord(this, ... 有什么区别吗?我想我没有抓住重点。我只是在读它
  • 我想使用这些事件而不是方法。使用事件我可以在某些情况下注册一些其他方法并通过调用事件来触发它们。但是通过调用方法,这是不可能的
  • 这听起来是个好理由。没想到。感谢您的解释和启发。
猜你喜欢
  • 1970-01-01
  • 2011-06-01
  • 2017-06-22
  • 2019-08-31
  • 2018-07-31
  • 1970-01-01
  • 2017-07-05
  • 2021-11-01
  • 2011-05-14
相关资源
最近更新 更多