Having children call parent's public events with data generated from a protected event
The events in the base class don't follow the standards:

public event Action&lt;TEventArgs&gt; DeviceArrived;
public event Action&lt;TEventArgs&gt; DeviceRemoved;

protected event Action&lt;string&gt; DeviceArrival;
protected event Action&lt;string&gt; DeviceRemoval;


I'd be expecting something like this:

public event EventHandler&lt;TEventArgs&gt; AfterDeviceArrived;
public event EventHandler&lt;TEventArgs&gt; AfterDeviceRemoved;

protected event EventHandler&lt;SomeEventArgsClass&gt; BeforeDeviceArrived;
protected event EventHandler&lt;SomeEventArgsClass&gt; BeforeDeviceRemoved;


Couple points:


Events can be declared with any delegate type (Action&lt;T&gt; works), but the convention is to use an EventHandler or EventHandler&lt;TEventArgs&gt; delegate.
Convention for naming events that come in pairs (raised before and after such or such "thing" happens) is to prefix the event names with "Before" and "After", and use past tense as you've done.
OnDeviceChange should be called OnDeviceChanged.. but it's not clear why the method needs to raise both ...Arrived and ...Removed events without [apparently] doing anything in-between.




A base class shouldn't know, or care, about whether it has derived classes or not. You've got that right, but a derived class that's listening for events raised in the base class, doesn't make sense to me.

I don't think events are the appropriate way to accomplish what you're trying to do here. That said I'm not sure exactly what you're trying to accomplish (trimmed code does that ;) - but I'd venture to suggest templated methods instead of events.

In the base class:

// todo: remove notion of "event args"
protected abstract void OnDeviceArrived(TEventArgs e);
protected abstract void OnDeviceRemoved(TEventArgs e);


The base class can call these methods even though they're not implemented - abstract methods must be implemented in the derived classes for the code to even compile.

So instead of this:

     if (e.Arrival &amp;&amp; DeviceArrived != null)
         DeviceArrived(e);
     if (!e.Arrival &amp;&amp; DeviceRemoved != null)
         DeviceRemoved(e);


You just have that:

    if (e.Arrival) 
    {
        OnDeviceArrived(e);
    }
    else
    {
        OnDeviceRemoved(e);
    }


And the derived classes have the implementations:

protected override void OnDeviceArrived(TEventArgs e)
{
    // ...
}

protected override void OnDeviceRemoved(TEventArgs e)
{
    // ...
}