Events: Custom Add and Remove with Global delegate cache. : event « GUI Windows Forms « C# / CSharp Tutorial






// copyright 2000 Eric Gunnerson
// From A Programmer's Introduction to C# 2.0, Third Edition

using System;
using System.Collections;
using System.Runtime.CompilerServices;

//
// Global delegate cache. Uses a two-level hashtable. The delegateStore hashtable 
// stores a hashtable keyed on the object instance, and the instance hashtable is 
// keyed on the unique key. This allows fast tear-down of the object when it's destroyed.
//
public class DelegateCache
{
    private DelegateCache() {}    // nobody can create one of these
    
    Hashtable delegateStore = new Hashtable();    // top level hash table
    
    static DelegateCache dc = new DelegateCache();    // our single instance
    
    Hashtable GetInstanceHash(object instance)
    {
        Hashtable instanceHash = (Hashtable) delegateStore[instance];
        
        if (instanceHash == null)
        {
            instanceHash = new Hashtable();
            delegateStore[instance] = instanceHash;
            
        }
        return(instanceHash);
    }
    
    public static void Combine(Delegate myDelegate, object instance, object key)
    {
        lock(instance)
        {
            Hashtable instanceHash = dc.GetInstanceHash(instance);        
            
            instanceHash[key] = Delegate.Combine((Delegate) instanceHash[key],
            myDelegate);
        }
    }
    
    public static void Remove(Delegate myDelegate, object instance, object key)
    {
        lock(instance)
        {
            Hashtable instanceHash = dc.GetInstanceHash(instance);        
            
            instanceHash[key] = Delegate.Remove((Delegate) instanceHash[key],
            myDelegate);
        }
    }
    
    public static Delegate Fetch(object instance, object key)
    {
        Hashtable instanceHash = dc.GetInstanceHash(instance);        
        
        return((Delegate) instanceHash[key]);
    }
    
    public static void ClearDelegates(object instance)
    {
        dc.delegateStore.Remove(instance);
    }
}

public class Button
{
    public void TearDown()
    {
        DelegateCache.ClearDelegates(this);
    }
    
    
    public delegate void ClickHandler(object sender, EventArgs e);
    
    static object clickEventKey = new object();
    
    public event ClickHandler Click
    {
        add
        {
            DelegateCache.Combine(value, this, clickEventKey);
        }
        
        remove
        {
            DelegateCache.Remove(value, this, clickEventKey);
        }
    }
    
    protected void OnClick()
    {
        ClickHandler ch = (ClickHandler) DelegateCache.Fetch(this, clickEventKey);
        
        if (ch != null)
        ch(this, null);
    }
    
    public void SimulateClick()
    {
        OnClick();
    }
}

class Test
{
    static public void ButtonHandler(object sender, EventArgs e)
    {
        Console.WriteLine("Button clicked");
    }
    
    public static void Main()
    {
        Button button = new Button();
        
        button.Click += new Button.ClickHandler(ButtonHandler);
        
        button.SimulateClick();
        
        button.Click -= new Button.ClickHandler(ButtonHandler);
        
        button.TearDown();
    }
}
Button clicked








23.64.event
23.64.1.Events
23.64.2.Using Event Accessors
23.64.3.Event and event handler
23.64.4.Use delegate to handle events
23.64.5.Fire event in property setter
23.64.6.Events: add and remove functions for a private delegate event
23.64.7.Events: add and remove functions
23.64.8.Events add and remove with synchronized block
23.64.9.Events: Custom Add and Remove with Global delegate cache.
23.64.10.A .NET-compatible event
23.64.11.Use the built-in EventHandler delegate
23.64.12.Use an anonymous method as an event handler
23.64.13.Ignored Parameters Anonymous Methods for Button click, kepressed and mouse clicked action
23.64.14.Events and form controls