I have a WCF service which accepts any entity which implements an interface. When it receives one of these entities I would like to publish an event i.e.
public void Receive(IFruit fruit)
{
messageHub.Publish(new FruitReceived<IFruit>(fruit));
}
However I would like to reify the interface so instead of everything that handles fruit subscribing to the event FruitReceived<IFruit> they can subscribe to only the type they're interested in such as FruitReceived<Apple>.
Currently I can do this through some lengthy reflection:
var fruitType = fruit.GetType();
var evt = typeof(FruitReceived<>)
.MakeGenericType(fruitType)
.GetConstructor(fruitType)
.Invoke(fruit);
This is a bit of a performance hit (even with caching the constructors) and also hard to read.
I was hoping that there's a simpler way to achieve this? I have spent so much time thinking about this solution that it's the only one I can come up with.
For reference the publish method simplifies to something like this:
public void Publish<TEvent>(TEvent evt)
{
if(_subscriptions.ContainsKey(typeof(TEvent))
{
IEnumerable<IEventHandler<TEvent>> handlers = _subscriptions[typeof(TEvent)];
foreach(var handler in handlers)
{
handler.HandleEvent(evt);
}
}
}
The underlying problem seems to be that you're receiving an instance of IFruit but downstream you want to distinguish between different concrete types.
The benefit of casting a class as an interface it implements is that consumers only need to know what the declared type is. They know it's an IFruit and that's all they need to know. As soon as they need to know more than that the benefit is reduced.
In other words, if you care at all about the difference between an Apple and an Orange then why cast it as an IFruit? Of course there are differences between implementations, but those differences - even the existence of different implementations - should be transparent to anything that depends on an IFruit.
There's no perfectly neat way to handle this. If you're not creating the generic type (as in your post) then you're doing this:
if(fruit is Apple)
There's going to be type creation or type inspection no matter what.
You could move the problem. Have a single event handler that handles FruitReceived<IFruit>. Then that event handler creates the more specific event type and re-raises it so that the more specific event handler can catch it. That way you can have event handlers specific to Apple, Orange, etc.
It's not perfect but it moves the problem from where the event is getting raised to another class that facilitates raising the more specific event type.
Another reason why this is beneficial is that your design allows for multiple event handlers. So conceivably you could raise FruitEvent<IFruit> where the concrete type is an Apple, so you want an apple-specific event handler, but you also want a generic IFruit event handler to execute. If you convert your event to FruitEvent<Apple> before raising it then you won't execute the generic event handler.
This can usually be solved with the visitor pattern. But it requires some extensive changes, starting with IFruit:
interface IFruitVisitor {
void Visit(Apple apple);
void Visit(Banana banana);
// ... you need a method for each fruit
}
interface IFruit {
Accept(IFruitVisitor visitor);
}
Then your fruits must implement that method:
class Apple : IFruit {
public void Accept(IFruitVisitor visitor) => visitor.Visit(this);
}
class Banana : IFruit {
public void Accept(IFruitVisitor visitor) => visitor.Visit(this);
}
And you can have a special visitor for your case:
class CreateFruitReceivedFruitVisitor : IFruitVisitor {
public object FruitReceived { get; private set; }
public void Visit(Banana banana) => FruitReceived = new FruitReceived<Banana>(banana);
public void Visit(Apple apple) => FruitReceived = new FruitReceived<Apple>(apple);
}
Then, just use it in your original method:
public void Receive(IFruit fruit)
{
var visitor = new CreateFruitReceivedFruitVisitor();
fruit.Accept(visitor);
messageHub.Publish(visitor.FruitReceived);
}
You need to weight in the benefits and costs of this solution. Even though it can be faster than the reflection version you showed, I believe it's much more unwieldy.
Related
I have read a few tutorials on the topic of the Decorator Pattern similar to this one. The basic example is a cake as in this tutorial, or a pizza as in other tutorials, and the decorators usually pass through values and modify them on the way (as in, every PizzaDecorator adds a small amount onto the price, thus returning the price of the pizza + all decorators). Now, that's certainly a nice example, but I am having a little trouble applying this to a less edible problem.
Suppose I have a base class that takes an input, according to which it modifies its state. Some of these state modifications cause an event to be raised which passes a value that could be considered the output. Now suppose the following features I'd like to individually add as decorators:
A buffer for the output
A history of the input
Another type of input (e.g. interprets a set of characters as allowed byte input values)
Individually, they are not so much of a problem. The basic functionality of the class (i.e. the TakeInput(byte input) and event Handler OutputAvailable) reside in an interface that the base class as well as the decorators can inherit (do I really need the extra abstraction layer as in the given example, i.e. a separate interface for the Decorator classes which in turn inherits from the base interface?). Now, if I implement the input cache in a decorator, how do I add it in such a way, that the next decorator would not hide it again? If I added, say, a list to simply store the input and made it available via a property, that property would be hidden should I decide that I also want the output buffered. I could keep references to both decorators around- but that would be rather messy, or so I think, because I am going to need quite a bunch of decorators. If I derived from the Decorator, the inheritance mess that I initially wanted to avoid by applying this pattern would not go away. How do I solve this problem?
As requested, a piece of code that illustrates my problem. (Or so I hope, anyway)
public interface ISampleClass
{
event OutputHandler OutputAvailable;
void TakeInput(byte input);
}
public class BaseSampleClass : ISampleClass
{
public event OutputHandler OutputAvailable;
void TakeInput(byte input)
{ // To keep things simple:
this.OutputAvailable(input);
}
}
public class SampleClassInputCacheDecorator : ISampleClass
{
private ISampleClass decoratedClass;
private List<byte> inputCache;
public event OutputHandler OutputAvailable;
public SampleClassInputCacheDecorator(ISampleClass decoratedClass)
{
this.decoratedClass = decoratedClass;
this.decoratedClass.OutputAvailable += (output) => {
this.OutputAvailable(output);
};
}
public List<byte> InputHistory { get { return this.inputCache; } }
public void TakeInput(byte input)
{
this.decoratedClass.TakeInput(input);
}
}
public class SampleClassCharInputAdapterDecorator : ISampleClass
{
private ISampleClass decoratedClass;
public SampleClassCharInputAdapterDecorator(ISampleClass decoratedClass)
{
this.decoratedClass = decoratedClass;
this.decoratedClass.OutputAvailable += (output) => {
this.OutputAvailable(output);
};
}
public void TakeInput(byte input)
{
this.decoratedClass.TakeInput(input);
}
public void TakeInput(char input)
{
switch (input)
{
case 'a':
this.TakeInput(27);
break;
case 'b':
// You get the idea...
}
}
}
// Now, I want to use the base class and get the benefit of both decorators:
ISampleClass smpl = new BaseSampleClass();
smpl = new SampleClassInputCacheDecorator(smpl);
smpl = new SampleClassCharInputAdapterDecorator(smpl);
// Dang, the input gets cached, but I can't access the InputHistory property.
Decorator is about altering the contracted behavior. You decorator adds completely new behavior, irrelevant in the context of the first one, and not being the part of the contract (the interface).
In fact SampleClassInputCacheDecorator is not a decorator - its actions are completely irrelevant from the ISampleClass point of view, as they don't influence TakeInput and OutputAvailable at all. It just depends on the ISampleClass chain, but does not "decorate" it. Proxy pattern seems more suitable here.
I have the following base interface
public interface IHandler{
void Handle(IMessage message);
}
and an generic interface inheriting the base interface
public interface IHandler<TMessage> : IHandler where TMessage : IMessage{
void Handle(TMessage message);
}
My classes can implement the interface IHandler<TMessage> mutiple times. IMessage is an base interface for messages and isn´t relevant here. Currently i´m implementing the interfaces as follows.
public class ExampleHandler : IHandler<ExampleMessage>, IHandler<OtherExampleMessag>{
void IHandler.Handle(IMessage message){
ExampleMessage example = message as ExampleMessage;
if (example != null) {
Handle(example);
}
else {
OtherExampleMessage otherExample = message as OtherExampleMessage;
if (otherExample != null) {
Handle(otherExample);
}
}
public void Handle(ExampleMessage) {
//handle message;
}
public void Handle(OtherExampleMessage) {
//handle message;
}
}
What bothers me is the way i have to implement the Handle(IMessage) method, cause in my opinion its many redundant code, and i have to extend the method each time when i implement a new IHandler<TMessage> interface on my class.
What i´m looking for is a more generic way to implement the Handle(IMessage) method (maybe in a base class for Handlers), but i´m currently stuck how to do that.
You can use the new dynamic keyword to move the overload resolution to the DLR:
void IHandler.Handle(IMessage message)
{
dynamic d = message;
Handle(d);
}
Please note that this will fail at runtime with a RuntimeBinderException if the message passed in is not valid for your class.
To avoid this exception you can add a Handler for all unknown message types:
private void Handle(object unknownMessage)
{
// Handle unknown message types here.
}
To implement IHandler.Handle in a base class, you need to do a little bit more work:
public class BaseHandler : IHandler
{
void IHandler.Handle(IMessage message)
{
dynamic d = message;
Handle(d);
}
private void Handle<TMessage>(TMessage message) where TMessage : IMessage
{
var handler = this as IHandler<TMessage>;
if(handler == null)
HandleUnknownMessage(message);
else
handler.Handle(message);
}
protected virtual void HandleUnknownMessage(IMessage unknownMessage)
{
// Handle unknown message types here.
}
}
Your specific handler would than look like this:
public class ExampleHandler : BaseHandler,
IHandler<ExampleMessage>,
IHandler<OtherExampleMessage>
{
public void Handle(ExampleMessage message)
{
// handle ExampleMessage here
}
public void Handle(OtherExampleMessage message)
{
// handle OtherExampleMessage here
}
}
This code now works like this:
The DLR calls the generic BaseHandler.Handle<TMessage> method with the real message type, i.e. TMessage will not be IMessage but the concrete message class like ExampleMessage.
In this geneirc handler method, the base class tries to case itself to a handler for the specific message.
If that is not successful, it calls HandleUnknownMessage to handle the unknown message type.
If the cast is successful, it calls the Handle method on the specific message handler, effectifly delegating the call to the concrete Handler implementation.
A reasonable way would be some judicious use of reflection:
var method = this.GetType().GetMethod("Handle", new[] { message.GetType() });
if (method != null) {
method.Invoke(this, new[] { message });
}
If you are doing this so much that performance is a problem you could cache the results of the test for a massive improvement.
You stuck because your class (in the question) does more than one thing. It deals with ExampleMessage and OtherExampleMessage. I suggest you create one class to handle one thing.
Example:
public class ExampleHandler : IHandler<ExampleMessage>
and
public class OtherExampleHandler : IHandler<OtherExampleMessag>
From my understanding, you want to have a class to handle some kind of events. In this case, you may have to use Observer pattern to notify each Handler when something happen and let they do their work.
The interfaces are saying that you have an instance that provides N services. Sure the services are similar but as they are for different types they are independent services. So your detecting a 'code smell'. The smell is 'why a common method for different services?'.
So are the services different enough to justify the generic interface declarations? The fundamental here is 'duplication'. Refactor out the duplication. Duplication is BAD. Once you move the duplicate stuff out then the answer will be self evident.
To put this another way, get rid of the common method and handle each in its own method ... the duplication is what you want to move out to another class. If so, think injection.
Love your smell detection!
I am trying to pass messages between several classes that communicate through interface. However, as I like to go as generic as possible, I ran into problems because the message type of incoming messages may be different from the outgoing type. I pasted some code to make it clearer.
The code below does not compile because the interface implementation passes a different type than the type of the blocking collection to which it is supposed to add incoming messages. I want to be able to send types potentially different from incoming types (incoming types obviously always match the type of the elements in the blocking collection). Can I somehow get around any sort of casting or parsing even if that means I need to redesign my interface or class?
I am still quite fresh when it comes to working with interfaces and struggled with recursions, stack overflow errors, and the like. So, if you have suggestions what I can improve design wise or just a quick fix then please help me to learn. Am very eager to understand how to implement a better pattern.
Thanks
public interface IClientMessaging
{
void MessagePassing<U>(U message);
}
public class InProcessMessaging<T> : IClientMessaging
{
private Dictionary<Type, List<IClientMessaging>> Subscriptions;
public BlockingCollection<T> MessageBuffer;
public InProcessMessaging(Dictionary<Type, List<IClientMessaging>> subscriptions)
{
//Setup Message Buffer
MessageBuffer = new BlockingCollection<T>();
//Subscribe
Type type = typeof(T);
if (subscriptions.Keys.Contains(type))
{
subscriptions[type].Add(this);
}
else
{
subscriptions.Add(type, new List<IClientMessaging>());
subscriptions[type].Add(this);
}
Subscriptions = subscriptions;
}
public void SendMessage<U>(U message)
{
//Send message to each subscribed Client
List<IClientMessaging> typeSubscriptions = Subscriptions[typeof(U)];
foreach (IClientMessaging subscriber in typeSubscriptions)
{
subscriber.MessagePassing<U>(message);
}
}
public T ReceiveMessage()
{
return MessageBuffer.Take();
}
public bool ReceiveMessage(out T item)
{
return MessageBuffer.TryTake(out item);
}
//Interface Implementation
public void MessagePassing<U>(U message)
{
MessageBuffer.Add(message); //<-"Cannot convert from U to T" [this is because I want
//to send messages of a different type than the receiving type]
}
}
I'm struggling to understand your goal here, but perhaps MessagePassing<U>(U message) should be MessagePassing(U message) and interface IClientMessaging should be interface IClientMessaging<U>.
Then InProcessMessaging<T, U> : IClientMessaging<U> - but I don't see why InProcessMessaging implements IClientMessaging AND manages subscriber lists of IClientMessaging. Seems to me that one class would manage the subscribers and another IS a subscriber (IClientMessaging).
You say U and T are different types. Well - are they related? Is one wrapper for the other? Sounds like maybe U is either a wrapper for T, a generic class itself that contains the T but adds extra info. In that case, void MessagePassing<T>(Wrapper<T> message);
UPDATES
Based on the comments so far ...
interface IClientMessage {}
interface IClientMessage<U> : IClientMessage { /* ... */ }
But rename those to:
interface IConsumer {} // (Or ISubscriber?)
interface IConsumer<TConsumed> : IConsumer{ /* ... */ }
and add:
interface IGenerator { }
interface IGenerator <TGenerated> : IGenerator {
event EventHandler<TGenerated> ItemGenerated;
}
Then:
class Manager
{
Dictionary<TConsumed, IConsumer> consumers = new ...
/* Code for attaching ItemGenerated event handlers to clients */
}
class MyClient : IGenerator<string>, IConsumer<Foo>, IConsumer<Bar>
{
event IGenerator<string>.ItemGenerated ...
void IConsumer<Foo>.Consume(...) ...
void IConsumer<Bar>.Consume(...) ...
}
Yes, this would use reflection to invoke IConsumer<TConsumed>.Consume(). Or you can leave off the generics and just use object as your types. Better yet, IClientMessage can have a Consume(object message) which in your implementation can ensure that object is a TConsumed before attempting to process it.
You could otherwise create direct client-to-client links through C# events, but you seem intent on a central dispatcher. It is the central dispatchers need to keep track of these different and unbounded number of types that is either going to require reflection OR be unaware of the types being passed (as described in the previous paragraph)
You should look at Reactive Extensions and the Observer pattern for ideas as well.
I removed my comments because it was getting too chatty.
I was triggered by this SO question about (.NET 4.0) covariance and contravariance support for Autofac, and now I'm trying to achieve something similar, but without any luck.
What I am trying to achieve is configure Autofac in such way that when I resolve a single concrete IEventHandler<TEvent> (for the sake of demonstration using container.Resolve, but normally of course using constructor injection), Autofac will return me a MultipleDispatchEventHandler<TEvent> that wraps all registered event handlers that are assignable from the requested handler.
In other words, when I write this:
var handler = container
.GetInstance<IEventHandler<CustomerMovedEvent>>();
handler.Handle(new CustomerMovedEvent());
With respect to the application design (given below), I'd expect a MultipleDispatchEventHandler<CustomerMovedEvent> to be returned that wraps both a CustomerMovedEventHandler and a NotifyStaffWhenCustomerMovedEventHandler.
Here is the application design:
// Events:
public class CustomerMovedEvent { }
public class CustomerMovedAbroadEvent : CustomerMovedEvent { }
public class SpecialCustomerMovedEvent : CustomerMovedEvent { }
// Event handler definition (note the 'in' keyword):
public interface IEventHandler<in TEvent>
{
void Handle(TEvent e);
}
// Event handler implementations:
public class CustomerMovedEventHandler
: IEventHandler<CustomerMovedEvent>
{
public void Handle(CustomerMovedEvent e) { ... }
}
public class NotifyStaffWhenCustomerMovedEventHandler
: IEventHandler<CustomerMovedEvent>
{
public void Handle(CustomerMovedEvent e) { ... }
}
public class CustomerMovedAbroadEventHandler
: IEventHandler<CustomerMovedAbroadEvent>
{
public void Handle(CustomerMovedAbroadEvent e) { ... }
}
This is the definition of the MultipleDispatchEventHandler<TEvent>, defined in the Composition Root:
// A composite wrapping possibly multiple handlers.
public class MultipleDispatchEventHandler<TEvent>
: IEventHandler<TEvent>
{
private IEnumerable<IEventHandler<TEvent>> handlers;
public MultipleDispatchEventHandler(
IEnumerable<IEventHandler<TEvent>> handlers)
{
this.handlers = handlers;
}
public void Handle(TEvent e)
{
this.handlers.ToList().ForEach(h => h.Handle(e));
}
}
This is my current configuration:
var builder = new ContainerBuilder();
// Note the use of the ContravariantRegistrationSource (which is
// available in the latest release of Autofac).
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof(IEventHandler<>).Assembly)
.AsClosedTypesOf(typeof(IEventHandler<>));
// UPDATE: I'm registering this last as Kramer suggests.
builder.RegisterGeneric(typeof(MultipleDispatchEventHandler<>))
.As(typeof(IEventHandler<>)).SingleInstance();
var container = builder.Build();
With the current configuration, the application fails during the call to Resolve, with the following exception:
Autofac.Core.DependencyResolutionException: Circular component
dependency detected:
MultipleDispatchEventHandler'1[[SpecialCustomerMovedEvent]] ->
IEventHandler'1[[SpecialCustomerMovedEvent]][] ->
MultipleDispatchEventHandler'1[[SpecialCustomerMovedEvent]].
Now the question is of course: how can I fix the configuration (or the design) to support this?
I'm going to make this a separate answer instead of modifying my other one. This one solves the example scenario without using a composite.
Working Code
I added a static int handleCount to each of the event handlers for testing purposes, like this:
public class CustomerMovedEventHandler
: IEventHandler<CustomerMovedEvent>
{
public static int handleCount = 0;
public void Handle(CustomerMovedEvent e) { handleCount++; }
}
Here's a passing test that demonstrates that the events are going where they should:
var builder = new ContainerBuilder();
builder.RegisterSource(new Autofac.Features
.Variance.ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof(IEventHandler<>).Assembly)
.AsClosedTypesOf(typeof(IEventHandler<>));
builder.RegisterGeneric(typeof(EventRaiser<>))
.As(typeof(IEventRaiser<>));
var container = builder.Build();
Assert.AreEqual(0, CustomerMovedEventHandler.handleCount);
Assert.AreEqual(0, NotifyStaffWhenCustomerMovedEventHandler.handleCount);
Assert.AreEqual(0, CustomerMovedAbroadEventHandler.handleCount);
container.Resolve<IEventRaiser<CustomerMovedEvent>>()
.Raise(new CustomerMovedEvent());
Assert.AreEqual(1, CustomerMovedEventHandler.handleCount);
Assert.AreEqual(1, NotifyStaffWhenCustomerMovedEventHandler.handleCount);
Assert.AreEqual(0, CustomerMovedAbroadEventHandler.handleCount);
container.Resolve<IEventRaiser<CustomerMovedAbroadEvent>>()
.Raise(new CustomerMovedAbroadEvent());
Assert.AreEqual(2, CustomerMovedEventHandler.handleCount);
Assert.AreEqual(2, NotifyStaffWhenCustomerMovedEventHandler.handleCount);
Assert.AreEqual(1, CustomerMovedAbroadEventHandler.handleCount);
container.Resolve<IEventRaiser<SpecialCustomerMovedEvent>>()
.Raise(new SpecialCustomerMovedEvent());
Assert.AreEqual(3, CustomerMovedEventHandler.handleCount);
Assert.AreEqual(3, NotifyStaffWhenCustomerMovedEventHandler.handleCount);
Assert.AreEqual(1, CustomerMovedAbroadEventHandler.handleCount);
You can see I'm using an IEventRaiser<TEvent> instead of a composite IEventHandler<TEvent>. Here's how it looks:
public interface IEventRaiser<TEvent>
{
void Raise(TEvent e);
}
public class EventRaiser<TEvent> : IEventRaiser<TEvent>
{
List<IEventHandler<TEvent>> handlers;
public EventRaiser(IEnumerable<IEventHandler<TEvent>> handlers)
{
this.handlers = handlers.ToList();
}
public void Raise(TEvent e)
{
handlers.ForEach(h => h.Handle(e));
}
}
Design Thoughts
Avoiding the composite IEventHandler sure makes our work at the composition root easier. We don't have to worry about recursive composition or making sure the composite is the default implementation. But we added a new interface IEventRaiser which might look redundant. Is it? I think not.
Raising an event and handling an event are two different things. IEventHandler is an interface that has to do with handling events. IEventRaiser is an interface that has to do with raising events.
Imagine that I'm a piece of code that wants to raise an event. If I ask the IoC for a single IEventHandler I am introducing coupling that I don't need. I shouldn't need to know about that IEventHandler interface. I shouldn't be asking anyone to Handle my event. All I want to do is Raise it. Handling may or may not happen on the other side; it is irrelevant to me. I'm selfish - I want an interface created solely for me and my need to raise events.
As an event raiser, I intend to raise an event. As an event handler, I intend to handle an event. We have two different intents, so we should have two different interfaces. Just because we could use the same interface and a composite doesn't mean we should.
The Interface Segregation Principle seems to be more about splitting fat interfaces into thinner ones (see also Role Interface). In our case, we don't have a fat interface, but I think we're doing something similar - "Interface Segregation by Intent".
One more thing
In writing this answer I almost articulated a design idiom that I think many of us are familiar with, but I don't think we have standard terminology for it.
"Type C Interface" - frequently Consumed, rarely Implemented. A "service" interface. For example, IEventRaiser or ICustomerRepository. These interfaces probably have only one implementation (maybe decorated a bit) but they are consumed all over the place by code that wants to Raise Events or Save Customers.
"Type I Interface" - frequently Implemented, rarely Consumed. A "plugin" interface. For example, IEventHandler<TEvent>. Consumed in only one place (the EventRaiser) but implemented by many classes.
The same interface should not be both a Type C and a Type I. This is another reason to separate the IEventRaiser (Type C) from the IEventHandler (Type I).
I'm thinking that the composite pattern is only applicable to Type C interfaces.
Please edit or comment if there is standard terminology for what I've called "Type C" and "Type I" interfaces.
+1 for IEventRaiser<T> by #default.kramer. Just for the record, since the linked answer doesn't provide any code, and the configuration for this scenario is a bit less than intuitive because of the generic types involved:
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(...)
.As(t => t.GetInterfaces()
.Where(i => i.IsClosedTypeOf(typeof(IEventHandler<>)))
.Select(i => new KeyedService("handler", i)));
builder.RegisterGeneric(typeof(MultipleDispatchEventHandler<>))
.As(typeof(IEventHandler<>))
.WithParameter(
(pi, c) => pi.Name == "handlers",
(pi, c) => c.ResolveService(
new KeyedService("handler", pi.ParameterType)));
Small question about C# language design :))
If I had an interface like this:
interface IFoo {
int Value { get; set; }
}
It's possible to explicitly implement such interface using C# 3.0 auto-implemented properties:
sealed class Foo : IFoo {
int IFoo.Value { get; set; }
}
But if I had an event in the interface:
interface IFoo {
event EventHandler Event;
}
And trying to explicitly implement it using field-like event:
sealed class Foo : IFoo {
event EventHandler IFoo.Event;
}
I will get the following compiler error:
error CS0071: An explicit interface implementation of an event must use event accessor syntax
I think that field-like events is the some kind of dualism for auto-implemented properties.
So my question is: what is the design reason for such restriction done?
Interesting question. I did some poking around the language notes archive and I discovered that this decision was made on the 13th of October, 1999, but the notes do not give a justification for the decision.
Off the top of my head I don't see any theoretical or practical reason why we could not have field-like explicitly implemented events. Nor do I see any reason why we particularly need to. This may have to remain one of the mysteries of the unknown.
I guess it might have to do with the fact that you can't call an explicit interface implementation from other members of the class:
public interface I
{
void DoIt();
}
public class C : I
{
public C()
{
DoIt(); // error CS0103: The name 'DoIt' does not exist in the current context
}
void I.DoIt() { }
}
Note that you can call the method by upcasting to the interface first:((I)this).DoIt();. A bit ugly but it works.
If events could be explicitly implemented as ControlFlow (the OP) suggested, then how would you actually raise them? Consider:
public interface I
{
event EventHandler SomethingHappened;
}
public class C : I
{
public void OnSomethingHappened()
{
// Same problem as above
SomethingHappened(this, EventArgs.Empty);
}
event EventHandler I.SomethingHappened;
}
Here you cannot even raise the event by upcasting to the interface first, because events can only be raised from within the implementing class. It therefore seems to make perfect sense to require accessor syntax for explicitly implemented events.
When explicitly implementing an event that was declared in an interface, you must use manually provide the add and remove event accessors that are typically provided by the compiler. The accessor code can connect the interface event to another event in your class or to its own delegate type.
For example, this will trigger error CS0071:
public delegate void MyEvent(object sender);
interface ITest
{
event MyEvent Clicked;
}
class Test : Itest
{
event MyEvent ITest.Clicked; // CS0071
public static void Main() { }
}
The correct way would be:
public delegate void MyEvent(object sender);
interface ITest
{
event MyEvent Clicked;
}
class Test : Itest
{
private MyEvent clicked;
event MyEvent Itest.Clicked
{
add
{
clicked += value;
}
remove
{
clicked -= value;
}
}
public static void Main() { }
}
see Compiler Error CS0071
This would not actually be an original thought by myself.
However, I thought I might respond to this:
"Off the top of my head I don't see any theoretical or practical reason why we could not have field-like explicitly implemented events. Nor do I see any reason why we particularly need to. This may have to remain one of the mysteries of the unknown."
-Eric Lippert
In Chapter 23 of A Programmer's Introduction to C#, Second Edition, Eric Gunnerson wrote:
"[I]f another class also wanted to be called when the button was clicked, the += operator could be used, like this:
button.Click += new Button.ClickHandler(OtherMethodToCall);
Unfortunately, if the other class wasn't careful, it might do the following:
button.Click = new Button.ClickHandler(OtherMethodToCall);
This would be bad, as it would mean that our ButtonHandler would be unhooked and only the new method would be called."
...
"What is needed is some way of protecting the delegate field so that it is only accessed using += and -=."
He goes on over the next few pages to comment on including the add() and remove() methods to implement this behavior; being able to write to those methods directly and the consequence of storage allocation for unneeded delegate references.
I would add more, but I respect the author too much to do so without his permission. I recommend finding a copy of this book and would recommend anything by Eric Gunnerson in general (blog, etc...)
Anyway, I hope this is relevant to the topic and if so, hope it shines light on this "mystery of the unknown"? (I was reading this very chapter and searching Stack Overflow for insight into event handler logic considerations when creating custom collections from custom objects) - I only mention this because I claim no specific authority on this particular subject. I am merely a student in search of "enlightenment" myself :-)