Joining an event of all objects in the list

Problem: I often find that I want to handle an event in a collection of objects. As objects are added and removed from the collection, each object must be connected or detached. I find it tedious and repeated to develop each class that does this with the same connection code.

Desired solution: So, I'm trying to come up with something like EventBindingListthat contains removable objects and allows the user to simultaneously connect several objects at once, as well as add and remove objects in the list.

To keep it common, you must use Reflection. In the list constructor, the user can specify EventInfo, or by the name of the event, which event is connected. It seemed the easiest way.

    private EventInfo _info;

    public EventBindingList(string EventName)
    {
        _info = typeof(T).GetEvents().Where(e => e.Name == EventName).First();
    }

    public EventBindingList(EventInfo info)
    {
        _info = info;
    }

I tried several approaches, but I'm still having problems with the differences between methods, delegates, lambdas and EventHandlers.

Bad Solution 1:

One of my solutions that didn’t work was to use a special accessory of events. This will be an event in the list containing the objects to be connected. This is due to the fact that when adding an EventHandler, an ArgumentException is thrown: Object of type 'System.EventHandler' cannot be converted to type 'ExternalProject.CustomEventHandler'.I tried to give the EventHandler the correct type (using universal type arguments, since this is an external project event handler), but the cast did not work.

    public event EventHandler ElementEvent
    {
        add
        {
            _handlers.Add(value);
            foreach (T t in this)
            {
                _info.AddEventHandler(t, value);
            }
        }
        remove
        {
            foreach (T t in this)
            {
                _info.RemoveEventHandler(t, value);
            }
            _handlers.Remove(value);
        }
    }

Bad Solution 2:

, , . , . .

: - , ?

+5
2

:

public abstract class ManagedEventCollection<T,TEventArgs> : IList<T>
{
   private EventInfo m_event;
   public ManagedEventCollection(string eventName)
   {
      m_list = new ObservableCollection<T> ();
      m_list.CollectionChanged += CollectionChanged;
      m_event = typeof (T).GetEvent (eventName);
   }
   // Add/Remove/Indexer/Clear methods alter contents of m_list.

   public EventHandler<TEventArgs> Handler{get;set;}

   protected abstract void OnItemAdded(T item);
   protected abstract void OnItemRemoved(T item);

   private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs ea)
   {
      foreach (T item in ea.NewItems)
      {
         m_event.AddEventHandler (
            item, 
            Delegate.CreateDelegate (m_event.EventHandlerType, item, Handler.Method));
      }
      foreach (T item in ea.OldItems)
      {
         m_event.RemoveEventHandler (
            item, 
            Delegate.CreateDelegate (m_event.EventHandlerType, item, Handler.Method));
      }
   }
}

: ObservableCollection<T>. CollectionChanged, / .

( , ).

public abstract class ManagedEventCollection<T> : IList<T>
{
   public ManagedEventCollection()
   {
      m_list = new ObservableCollection<T> ();
      m_list.CollectionChanged += CollectionChanged;
   }
   ... // Add/Remove/Indexer/Clear methods alter contents of m_list.
   protected abstract void OnItemAdded(T item);
   protected abstract void OnItemRemoved(T item);

   private ObservableCollection<T> m_list;
   private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs ea)
   {
      foreach (T item in ea.NewItems)
         OnItemAdded(item);
      foreach (T item in ea.OldItems)
         OnItemRemoved(item);
   }
}

:

public class DogManagedEventCollection : ManagedEventCollection<Dog>
{
   protected override OnItemAdded (Dog dog)
   {
      dog.Bark += Bark;
   }
   protected override OnItemRemoved (Dog dog)
   {
      dog.Bark -= Bark;
   }

   private void Bark(object sender, BarkEventArgs ea){...}
}

, , //.

+4

, :).

- , - ObservableCollection , (, , , )?

public class MyEventList<TElementType,TEventArgType>: IList<TElementType> where TEventArgType: EventArgs
{
    private EventInfo eventInfo;
    private EventHandler<TEventArgType> eventHandler;

    public MyEventList(string eventName, EventHandler<TEventArgType> eventHandler)
    {
        if (eventHandler == null)
            throw new ArgumentNullException("eventHandler");
        if (eventName == null)
            throw new ArgumentNullException("eventName");

        this.eventInfo = typeof(TElementType).GetEvent(eventName);

        if (this.eventInfo == null)
            throw new ArgumentException("Specified event not found.", "eventName");

        if (this.eventInfo.EventHandlerType != eventHandler.GetType())
            throw new ArgumentException("EventHandler type does not match specified event.", "eventHandler");

        this.eventHandler = eventHandler;
    }

    public void Add(TElementType item)
    {
        ...
        eventInfo.AddEventHandler(item, this.eventHandler);
        ...
    }

    public bool Remove(TElementType item)
    {
        ...
        eventInfo.RemoveEventHandler(item, this.eventHandler);
        ...
    }

    ...

 }
+1

All Articles