次の方法で共有


using (start/end)

I'm trying to build something similar to the TimedLock class, but for start & end events. I want to be able to use it like this:

                  using (this.StartEndEvent.Open(this))

                  {

                        // ... do something

                  }

Which would mean:

                  this.StartEndEvent.OnStart(this);

                  // ... do something

                  this.StartEndEvent.OnEnd(this);

(add try/finally as needed).

Here’s my first cut. Can we make it better?

      class StartEndEvent : IDisposable

      {

            public event EventHandler OnStart;

            public event EventHandler OnEnd;

            object _sender;

            public IDisposable Open(object sender)

            {

                  this._sender = sender;

                  this.OnStart(_sender, null);

                  return (IDisposable)this;

            }

            void IDisposable.Dispose() { this.OnEnd(_sender, null); }

      }

Comments

  • Anonymous
    June 14, 2004
    I would go with a method returning StartEndEvent object and put the Open code into its ctor. That way the usage would be a little more intuitive and safe (in your version you can have multiple using blocks using the same object, since you're not creating a new one but sharing an existing.
  • Anonymous
    June 14, 2004
    The comment has been removed
  • Anonymous
    June 14, 2004
    Why not go all the way?

    public class EventSpanner : IDisposable
    {
    private readonly EventHandler _end;
    private readonly object _sender;

    public EventSpanner(object sender, EventHandler start, EventHandler end)
    {
    _sender = sender;
    start(sender, EventArgs.Empty);
    _end = end;
    }

    void IDisposable.Dispose()
    {
    _end(_sender, EventArgs.Empty);
    }
    }


    Then, you could go:

    public class Machinery
    {
    public event StartMachinery;
    public event StopMachinery;
    public void Run()
    {
    using(new EventSpanner(this, StartMachinery, StopMachinery))
    {
    // "machinate"
    }
    }
    }
  • Anonymous
    June 15, 2004
    I have to apologize. This post was written up in great haste, and the code still has plenty of room for improvement.

    Dmitry:

    I was thinking that the Start and Stop events should be owned by the EventSpanner. Having the Machinery class expose the EventSpanner seems beneficial. Then the consumer sees the semantic relationship of the events being supported by the class structure.

    Consider if there was a 3rd, unrelated event. Seeing:

    - OnStart
    - OnEnd
    - OnFire

    I see that OnStart and OnEnd are a pair, and belong together; that they are somehow more like each other than like OnFire.

    - SpannedEvent.OnStart
    - SpannedEvent.OnEnd

    - OnFire

    What do you think?
  • Anonymous
    June 15, 2004
    No need to apologize. This is a blog, not an online magazine. We expect you to be imperfect :)

    Here's my reasoning on this. By making EventSpanner generic, you make it a pattern. Now, not only Machinery, but also KnotTyingCompetition can enjoy the benefit of the same EventSpanner.

    If the sequence of events fired is controlled from the inside of the class that hosts the events, there is no reason to have EventSpanner as member of the hosting class and thus, no reason for Start and End events to be owned by EventSpanner.

    What do you think back at ya.
  • Anonymous
    June 15, 2004
    Maybe we can decompose the problem further. I see several notions:

    1. Do something before and after something else.

    2. Fire a given event before and after something else.

    3. Manage OnStart and OnEnd events.

    So I think I would make 3 classes, each based on the previous.

    This hits both what you were doing & what I was doing.
  • Anonymous
    June 15, 2004
    Sounds good.

    Do you think a controller-type situation would work well?

    EvenSpannerBase(IEventSpanEnabled subject)
    {
    _subject = subject;
    _subject.Start();
    }

    void IDisposable.Dispose()
    {
    _subject.End();
    }

  • Anonymous
    July 05, 2006
    using pattern