如何使用自定义事件访问器在c#中添加事件时调用方法?

时间:2011-04-23 16:44:51

标签: c# .net

我正在读这个 http://msdn.microsoft.com/en-us/library/bb882534.aspx

我不清楚如何做到这一点。

更新:由于有些人已经回答了这些主持人是如何假装这个问题含糊不清的?

3 个答案:

答案 0 :(得分:4)

这是一个如何处理自定义事件访问器的简单示例,我知道您希望每次从事件附加/分离事件处理程序时调用函数。在这种情况下,您需要在下面的代码中创建一个私有支持委托myCustomEventDelegate,并让您的自定义事件访问者add/remove阻止向委托添加/删除处理程序,当然还会调用您的其他功能。

在这个示例中,我只是写入控制台,当然,如果您的代码是可以在可能无法访问控制台的不同类型的应用程序中使用的库的一部分,那么这不是一个好主意,但它是毕竟只是一个例子。

using System;

namespace CustomEventDemo
{
  class Program
  {
    static void Main(string[] args)
    {
      TheClassExposingYourEvent instance = new TheClassExposingYourEvent();

      instance.MyCustomEvent += new EventHandler<EventArgs>(Program_MyCustomEvent);
      instance.DoSomething();
      instance.MyCustomEvent -= new EventHandler<EventArgs>(Program_MyCustomEvent);

      Console.ReadKey();
    }

    static void Program_MyCustomEvent(object sender, EventArgs e)
    {
      Console.WriteLine("The event was fired");
    }
  }

  class TheClassExposingYourEvent
  {
    private EventHandler<EventArgs> _myCustomEventDelegate;
    public event EventHandler<EventArgs> MyCustomEvent
    {
      add
      {
        _myCustomEventDelegate += value;
        // Do something extra here.
        // Writing to the console is a bad example!!!
        Console.WriteLine("Event handler attached");
      }
      remove
      {
        _myCustomEventDelegate -= value;
        // Do something extra here.
        // Writing to the console is a bad example!!!
        Console.WriteLine("Event handler detached");
      }
    }

    public void DoSomething()
    {
      if (_myCustomEventDelegate != null)
      {
        _myCustomEventDelegate(this, EventArgs.Empty);
      }
    }
  }
}

答案 1 :(得分:1)

不是这样的吗?

    event EventHandler IDrawingObject.OnDraw
    {
        add
        {
            lock (PreDrawEvent)
            {
                PreDrawEvent += value;
            }
            YourFunction();  // HERE
        }

答案 2 :(得分:1)

事件实际上是非公共委托,它们是添加/删除访问器的包装器,用于限制外部类可以修改委托的方式。下面的代码虽然冗长,但却详细说明了代表和事件。它来自我为同事学习.Net而放在一起的示例项目。像书一样从上到下阅读(添加注释以进行解释,但代码编译):

// http://msdn.microsoft.com/en-us/library/aa288459(VS.71).aspx

// delegates are a lot like function pointers and events "appear" to be a lot like delegates.
// in a sense, a delegate is a function pointer class.  below is an example declaration
// of a delegate with an int return value, and two parameters (bool, string)
public delegate int MyDelegate(bool abool, string astring);

// delegates behind the scenes are actually of the System.MulticastDelegate type, and therefore
// can have multiple invocations.
// see http://msdn.microsoft.com/en-us/library/system.multicastdelegate.aspx

class DelegatesAndEvents
{

    // delegates can also be defined inside classes
    public delegate void AnotherDelegate();

    // Delegates can be instantiated just like any variable or field
    public AnotherDelegate DelegateInstance;

    public DelegatesAndEvents()
    {
        // add method/delegate to the invocation list
        DelegateInstance += Method;
        // or another syntax
        DelegateInstance += new AnotherDelegate(Method);

        // remove a method/delegate to the invocation list
        DelegateInstance -= Method;
        // or the more formal syntax
        DelegateInstance -= new AnotherDelegate(Method);

        // set the invocation list to a single method/delegate
        DelegateInstance = Method;
        // or the more formal syntax
        DelegateInstance = new AnotherDelegate(Method);

        // to clear a delegate, assign it to null:
        DelegateInstance = null;

        // for all the previous operators, its very important to note
        // that they instantiate a new MulticastDelegate in the process.
        // this means that every add (+=) or remove(-=) generates a new
        // MulticastDelegate.  Look at the following scenario:
        DelegateInstance = Method;

        // invoking a will call Method
        AnotherDelegate a = DelegateInstance;

        DelegateInstance += AnotherMethod;
        // now, invoking a will still only invoke Method, while
        // invoking DelegateInstance will invoke both Method
        // and AnotherMethod.

        // NOTE NOT BEST PRACTICE SEE BELOW
        a(); // invokes Method
        DelegateInstance(); // invokes Method and AnotherMethod

        // The main importance of this fact deals with thread safety
        // when invoking delegates.  When invoking a delegate, you
        // should always do a null-check before invocation to avoid
        // an exception:

        // NOTE NOT BEST PRACTICE SEE BELOW
        if (a != null)
        {
            a();
        }

        // the problem with the above code is that if another thread removes
        // Method from a, after the null check, trying to invoke a will throw
        // an exception.  To get around this, since we stated before that the
        // remove operation recreates the MulticastDelegate, assigning the
        // delegate to a temporary delegate before doing the null check, and
        // then invoking that temporary delegate should avoid threading problems

        //**************************************************************
        // NOTE THIS IS BEST PRACTICE FOR INVOKING A DELEGATE/EVENT
        // This is thread-safe
        AnotherDelegate aCopy = a;
        if (aCopy != null)
        {
            aCopy();
        }
        //**************************************************************
    }

    // NOTE there is a way to avoid having to worry about null checking, with only
    // a small overhead.  assigning a delegate/event to an initial no-op function will
    // simplify how it is invoked:

    public AnotherDelegate ThirdDelegate = delegate { }; // this assigns a no-op delegate

    // using this method, you'll be able to call the delegate without checking for
    // null or use a temporary variable.  this of course is only true if no code
    // sets ThirdDelegate to null anywhere.

    public void Method()
    {
        // Delegates can be instantiated just like any variable or field
        MyDelegate x = AFunction; // shorthand way of creating a delegate from an actual function
        x = new MyDelegate(AFunction); // the more formal way of creating a delegate

        // if a delegate hasn't been assigned anything, trying to call it will throw an exception
        // not really necessary here though since we just assigned it
        if (x != null)
        {
            int somevalue = x(false, "10");
        }
    }

    public void AnotherMethod()
    {
        // Do Nothing
    }

    public int AFunction(bool somebool, string somestring)
    {
        if (somebool)
        {
            return 1;
        }
        int avalue;
        if (int.TryParse(somestring, out avalue))
        {
            return avalue;
        }
        return 0;
    }

    // EVENTS

    // events are types as delegates but avoid a couple of issues with
    // instantiating delegates as members of a class.  unlike delegates
    // events can only be created within a class or struct (ie not as
    // a standalone type in a namespace).  to create an event, add the
    // event keyword:

    public event AnotherDelegate AnotherEvent;

    // the above is actually the shorthand way of instantiating an event
    // the full way is below:

    private MyDelegate someEvent;
    public event MyDelegate SomeEvent
    {
        add
        {
            someEvent += value;
        }
        remove
        {
            someEvent -= value;
        }
    }

    // EXPLANATION OF HOW AN EVENT DIFFERS FROM A DELEGATE
    // events are actually similar to properties in that they wrap a
    // non-public delegate.  this prohibits an external source from
    // doing two things that most likely aren't desired:
    // external code can't invoke the delegate
    //    external code can't do: classInstance.SomeEvent(...parameters...);
    // external code can't set the delegate
    //    external code can't do: classInstance.SomeEvent = somedelegate;
    // this effectively makes an event something that occurs within class, and
    // controlled by the class, but can be subscribed to by external code.

    // events usually derive from the EventHandler or EventHandler<T> delegates
    // which have the following definitions:
    // void EventHandler(object sender, EventArgs e)
    // void EventHandler<T>(object sender, T e)
    // the common way to use these is to always send the class instance that
    // raised the event, as well as some event arguments that contain more
    // information about the event.  see below for an example of extending
    // EventArgs.

    public event EventHandler<TakeOffEventArgs> TakeOff;
    public void PerformTakeOff()
    {
        EventHandler<TakeOffEventArgs> takeOffTemp = TakeOff;
        if (takeOffTemp != null)
        {
            takeOffTemp(this, new TakeOffEventArgs("Spaceship", double.MaxValue));
        }
    }
}

public class TakeOffEventArgs : EventArgs
{
    public TakeOffEventArgs(string aircraft, double speed)
    {
        Aircraft = aircraft;
        Speed = speed;
    }

    public string Aircraft { get; set; }
    public double Speed { get; set; }
}