Explicit Interface Implementation And Events

C

COLIN JACK

Hi All,

I've got a situation where I'm implementing an interface (BaseInterface in
example below) and I want to use explicity interface implementation of an
event so that I can add type safety. To see what I mean look at the example
below where the class implementing the interface actually wants the event to
be for a more specific delegate.

Now this seems to work but the code, to me is unnecessarily ugly. This
leaves me wondering if this is something other people do and if so is there
a better way of doing it?

I should also say the reason I'm doing it is in a real situation I want to
have a class implementing an interface raising the event with EventArguments
that are derived from the ones that the delegate in the interface uses,
doing so stops me having to cast the event arguments in the event handler.

Thanks in advance,

Colin Jack


public delegate void GeneralEventHandler(object sender, GeneralEventArgs
ex);
public delegate void SpecificEventHandler(object sender, SpecificEventArgs
ex);

public class GeneralEventArgs : EventArgs
{
public string general = "General";
}

public class SpecificEventArgs : GeneralEventArgs
{
public string specific = "Specific";
}


public interface BaseInterface
{
event GeneralEventHandler GeneralEvent;
}

public class ConcreteClassSpecific: BaseInterface
{
// explicit interface implementation, I need to actually specify
// the add/remove accessors
GeneralEventHandler specificEvent;
event InheritanceTest.GeneralEventHandler BaseInterface.GeneralEvent
{
add
{
specificEvent += value;
}
remove
{
specificEvent -= value;
}
}

// This means that subscribers have to use SpecificEventHandler which
// allows them to access its specific string field
public event SpecificEventHandler GeneralEvent;

protected void OnEvent()
{
if (specificEvent != null)
{
specificEvent(null, new GeneralEventArgs());
}

if (GeneralEvent != null)
{
GeneralEvent(this, new SpecificEventArgs());
}
}

public void RaiseEvent()
{
OnEvent();
}
}
 
D

Dave

I don't see your implementation as necessarily, "sloppy", however the design patter for delegates states the use of "object" as
sender and "EventArgs" as the args for the fact that certain events may require usage of different "senders" and "args" which these
base types will allow via inheritance. To prevent having to cast, I think your solution is fine.

I'd also like to say that it may not be the best design to have an interface event "overriden". The purpose of an Interface is to
provide a contract, but your breaching this contract. Maybe you should have a different event on the implementing type named,
"SpecificEvent" along side of the implementation for "GeneralEvent". It's hard to say without knowing the business logic behind the
events themselves.

BTW, your accessors are using "specificEvent+=" when they should be using "GeneralEvent+=", correct? Maybe just an oversight:
event InheritanceTest.GeneralEventHandler BaseInterface.GeneralEvent
{
add
{
specificEvent += value;
}
remove
{
specificEvent -= value;
}
}
 
C

colinjack

Hi Dave,

Thanks for the reply, very useful to read someone else's opinion.

First off yes using the "specificEvent" was an oversight, I should have
read through the code before posting :)

However I dont see that i'm breaking the contract. I say this because
you can still subscribe to and receive the GeneralEvent using the
GeneralEventHandler delegate if you cast the publisher
(ConcreteClassSpecific) to the interface(BaseInterface). However if
you, as a subscriber, want the more specific event arguments then you
subscribe to the event using a normal reference to the object (using a
ConcreteClassSpecific reference). I've tried to show this in the
attached snippet.

I may be wrong but I see this as the same as using explicit interface
implementation to provide type safety with methods.

Your right about me trying to avoid following the normal event desing
pattern as I dont like the idea that I'm raising an event and the
receiver actually knows that the event args are a derived class so they
do a cast.

Ta,

Colin


private void SubscribeToEvents()
{
ConcreteClassSpecific myObject = new ConcreteClassSpecific();
myObject.GeneralEvent += new
SpecificEventHandler(specific_GeneralEvent);

BaseInterface interfaceBase = (BaseInterface)myObject;
interfaceBase.GeneralEvent +=new
GeneralEventHandler(interfaceBase_GeneralEvent);

myObject.RaiseEvent();
}

private void specific_GeneralEvent(object sender, SpecificEventArgs
ex)
{
}

private void interfaceBase_GeneralEvent(object sender,
GeneralEventArgs ex)
{
}
I don't see your implementation as necessarily, "sloppy", however the
design patter for delegates states the use of "object" as
sender and "EventArgs" as the args for the fact that certain events
may require usage of different "senders" and "args" which these
base types will allow via inheritance. To prevent having to cast, I think your solution is fine.

I'd also like to say that it may not be the best design to have an
interface event "overriden". The purpose of an Interface is to
provide a contract, but your breaching this contract. Maybe you
should have a different event on the implementing type named,
"SpecificEvent" along side of the implementation for "GeneralEvent".
It's hard to say without knowing the business logic behind the
events themselves.

BTW, your accessors are using "specificEvent+=" when they should be
using "GeneralEvent+=", correct? Maybe just an oversight:
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top