Collection of generic handlers - is this possible? - c#

Using generics is it possible to have a generic collection defined as a base type and assign instances of a sub type? I have a simple code sample below that highlights my thinking and the line that causes the compiler error. I know that I could create a IEventHandler marker interface and make my generic event handlers inherit from that. This would let me store the generic types within a collection of IList, but this seems less than ideal. Is there a way similar to the code I have below?
using System;
using System.Collections.Generic;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
IEventHandler<SomeEvent1> handler1 = new SomeEvent1Handler();
IEventHandler<SomeEvent2> handler2 = new SomeEvent2Handler();
IList<IEventHandler<IEvent>> handlers = new List<IEventHandler<IEvent>>();
// COMPILE ERROR - is this possible?
handlers.Add(new SomeEvent1Handler());
}
public interface IEvent {
}
public interface IEventHandler<in TEvent> where TEvent : IEvent
{
void Handle(TEvent someEvent);
}
public class SomeEvent1 : IEvent {
}
public class SomeEvent2 : IEvent {
}
public class SomeEvent1Handler : IEventHandler<SomeEvent1>
{
public void Handle(SomeEvent1 someEvent)
{
throw new NotImplementedException();
}
}
public class SomeEvent2Handler : IEventHandler<SomeEvent2>
{
public void Handle(SomeEvent2 someEvent)
{
throw new NotImplementedException();
}
}
}
}

Using generics is it possible to have a generic collection defined as
a base type and assign instances of a sub type?
Yes, but It could only be done if your interface was IEventHandler<out TEvent>, you can't do it with in.
If your code did work, what would you expect to happen if the code was
public static void Main(string[] args)
{
IList<IEventHandler<IEvent>> handlers = new List<IEventHandler<IEvent>>();
handlers.Add(new SomeEvent1Handler()); //Magicly works
IEventHandler<IEvent> handler = handlers[0];
handler.Handle(new SomeEvent2());
}
handler states it allows any IEvent to be passed in to its Handle function. This would cause SomeEvent1Handler would be passed a SomeEvent2 object to its public void Handle(SomeEvent1 someEvent) method.
My work around would be have the handlers just take in a IEvent, in the function they check if it is a type of event they don't care about they can just return from the function without doing anything.
using System;
using System.Collections.Generic;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
IEventHandler<SomeEvent1> handler1 = new SomeEvent1Handler();
IEventHandler<SomeEvent2> handler2 = new SomeEvent2Handler();
IList<IEventHandler> handlers = new List<IEventHandler>();
handlers.Add(new SomeEvent1Handler());
}
public interface IEvent {
}
public interface IEventHandler
{
void Handle(IEvent someEvent);
}
public class SomeEvent1 : IEvent {
}
public class SomeEvent2 : IEvent {
}
public class SomeEvent1Handler : IEventHandler
{
public void Handle(IEvent someEvent)
{
var event = someEvent as SomeEvent1;
if(event == null)
return;
//Do stuff here.
}
}
public class SomeEvent2Handler : IEventHandler
{
public void Handle(IEvent someEvent)
{
var event = someEvent as SomeEvent2;
if(event == null)
return;
//Do stuff here.
}
}
}
}

This cannot be done as it is not safe - if it were allowed you could do:
var handlers = new List<IEventHandler<IEvent>> { new SomeEvent1Handler() };
handlers[0].Handle(new SomeEvent2());
I suggest you create a wrapper class around a typed handler e.g.
public class HandlerWrapper<T> : IEventHandler<IEvent>
{
private readonly IEventHandler<T> inner;
public HandlerWrapper(IEventHandler<T> inner)
{
this.inner = inner;
}
public void Handle(IEvent event)
{
if(event is T) { inner.handle((T)event); }
else throw new ArgumentException("Unexpected event type");
}
}
You can now create an IList<EventHandler<IEvent>> and you will need to manage the dispatch to the correct handler dynamically.

Related

C# polymorphous design without casting

I have Generator class that generates objects with different Interfaces with different probabilities. All objects generated by Generator is of type BaseClass. BaseClass is an abstract base class.
Lets say interfaces are I1, I2
I have another class Resolver that has polymorphic method for two interfaces as follows:
Resolve(I1 myObj){//code for I1}
Resolve(I2 myObj){//code for I2}
The main class looks like this:
BaseClass event = Generator.generate(); //event is implements I1 or I2. Not known what interfaces until run time.
Resolver.Resolve(event); //Here i got an error, because event is BaseClass type and not I1 or I2 type.
Is there a way to solve this issue without explicitly check Interface type and cast it to appropriate interface. I came from python background, so statically typed language is new for me.
Consider using dependency injection to allow the event object to call the Resolver itself.
public interface IResolvable
{
void Resolve(Resolver resolver);
}
public interface I1 : IResolvable { //... }
public interface I2 : IResolvable { //... }
public class Resolver
{
public void Resolve(I1 i) { //... }
public void Resolve(I2 i) { //... }
}
public abstract class BaseClass : IResolvable
{
public abstract void Resolve(Resolver resolver);
//...
}
An implementation would look something like:
public class Implementation1 : BaseClass, I1
{
public override void Resolver(Resolver resolver)
{
resolver.Resolve(this);
}
//...
}
And then calling it:
Resolver resolver = new Resolver();
IResolvable evnt = Generator.Generate();
evnt.Resolve(resolver);
We can go a step further and make an interface for Resolver, so we can mock it for unit testing purposes and take full advantage of the DI pattern.
public interface IResolver
{
void Resolve(I1 i) { //... }
void Resolve(I2 i) { //... }
}
Then we change the definition of IResolvable
public interface IResolvable
{
void Resolve(IResolver resolver);
}
Here is some code that demonstrates virtual function approach that doesn't need casting.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication3
{
interface IBase
{
void Function();
}
class BaseClass : IBase
{
public virtual void Function()
{
}
}
interface I1: IBase
{
}
interface I2 : IBase
{
}
class C1: BaseClass, I1
{
public override void Function()
{
Console.WriteLine("Hello from C1");
}
}
class C2 : BaseClass, I1
{
public override void Function()
{
Console.WriteLine("Hello from C2 !!!");
}
}
static class Generator
{
public static BaseClass generateC1()
{
return new C1();
}
public static BaseClass generateC2()
{
return new C2();
}
}
class Program
{
static void Main(string[] args)
{
BaseClass b1 = Generator.generateC1();
b1.Function();
Console.WriteLine("-------");
BaseClass b2 = Generator.generateC2();
b2.Function();
Console.WriteLine("End!");
}
}
}
EDIT I adjusted my answer because I did not understand the question correctly the first time.
I think that you can not achieve exactly what you would like to without using casts. As far as I understand as soon as you reference the object you get from Generator.generate() by its base type it is not possible to access the object by its specialized type again without casting it.
I can think of two alternatives which might be interesting for you. One is using C# 7 pattern matching (which is a bit like using casts) and the other is using dynamic.
Pattern matching
using System;
namespace EventREsolver
{
public interface IEvent { }
public class Event1 : IEvent { }
public class Event2 : IEvent { }
public class Resolver
{
public void Resolve(IEvent theEvent)
{
switch (theEvent)
{
case Event1 e1: Resolve(e1); break;
case Event2 e2: Resolve(e2); break;
default: throw new ArgumentException("not a recognized type", nameof(theEvent));
}
}
private void Resolve(Event1 theEvent)
{
Console.WriteLine("Resolve I1");
}
private void Resolve(Event2 theEvent)
{
Console.WriteLine("Resolve I2");
}
}
public class Generator
{
int state = 0;
public IEvent Generate()
{
if (state == 0)
{
state++;
return new Event1();
}
return new Event2();
}
}
class Program
{
static void Main(string[] args)
{
var generator = new Generator();
var event1 = generator.Generate();
var event2 = generator.Generate();
var resolver = new Resolver();
resolver.Resolve(event1);
resolver.Resolve(event2);
Console.ReadKey();
}
}
}
Dynamic
using System;
namespace EventREsolver
{
public interface IEvent { }
public class Event1 : IEvent { }
public class Event2 : IEvent { }
public class Resolver
{
public void Resolve(Event1 theEvent)
{
Console.WriteLine("Resolve I1");
}
public void Resolve(Event2 theEvent)
{
Console.WriteLine("Resolve I2");
}
}
public class Generator
{
int state = 0;
public IEvent Generate()
{
if (state == 0)
{
state++;
return new Event1();
}
return new Event2();
}
}
class Program
{
static void Main(string[] args)
{
var generator = new Generator();
dynamic event1 = generator.Generate();
dynamic event2 = generator.Generate();
var resolver = new Resolver();
resolver.Resolve(event1);
resolver.Resolve(event2);
Console.ReadKey();
}
}
}

implementing delegate in interface

I can't find a way to implement delegate in interface
I want to get this:
public class SomeClass : ISomeInterface
{
public delegate void SomeCallback();
public SomeCallback callback;
public void SomeMethod()
{
callback.invoke();
}
}
public class MainClass
{
void Callback() { Console.WriteLine("Callback"); }
public void Start()
{
SomeClass s = new SomeClass();
s.callback = Callback;
s.SomeMethod();
}
}
but in case when I create instance of the class "SomeClass" using interface:
public class MainClass
{
void Callback() { Console.WriteLine("Callback"); }
public void Start()
{
ISomeInterface s = new SomeClass(); // <<<----
s.callback = Callback; // here will be an error :(
s.SomeMethod();
}
}
Please, help me with it :)
Moving the callback to the interface is required if you want to use the callback without casing to a concrete type. Note that your current implementation has callback as a field. To declare it in an interface, you must make it a property.
Because properties are really methods, you must implement the property in your concrete class. Using an auto-property is fine for the implementation here.
Once you've made those changes, you can then set and call the callback using only the interface.
public delegate void SomeCallback();
public interface ISomeInterface {
SomeCallback callback { get; set; }
void SomeMethod();
}
public class SomeClass : ISomeInterface
{
public SomeCallback callback { get; set; }
public void SomeMethod()
{
callback.Invoke();
}
}
public class MainClass
{
void Callback() { Console.WriteLine("Callback"); }
public void Start()
{
ISomeInterface s = new SomeClass();
s.callback = Callback;
s.SomeMethod();
}
}

Dynamically combine classes in order to remove responsibilities from API

I'm building an API (for a game-engine) which exposes two interfaces called IWindow and IEngineWindow.
The IWindow interface is supposed to be implemented by an API-user and the IEngineWindow interface is used by the engine to interact with the window.
The window object should have a private member of the type List<IWindowControl>.
I could use an abstract class and get rid of the interfaces but then i would have implementation-details in my API which i don't want.
My theoretical solution to the problem is that the API-user implements IWindow in his own class and calls a method (something like GetEngineWindow(typeof(MyWindowClass))) which returns an object which is identical to an instance of MyWindowClass except that it also implements the IEngineWindow interface.
I was planning to use System.Reflection.Emit in the GetEngineWindow() method to dynamically combine MyWindowClass with an internal class which implements the IEngineWindow interface but i quickly realised that this would be a mayor project of it's own.
My question boils down to if there is a simpler solution to remove this kind of implementation-details from an API or if there exists a library (free for commercial use) to do this kind of class-fusing.
In case my question is too abstract, here is a code example of what i want to be able to do:
//API (dll-file)
interface IWindow
{
void BeforeClose();
}
interface IEngineWindow
{
void Show();
}
//Built into engine (written by me)
class Program
{
static void Main(string[] args)
{
object window = CombineClasses(typeof(Testwindow), typeof(EngineWindow));
((IWindow)window).BeforeClose(); //Outputs: Closing...
((IEngineWindow)window).Show(); //Outputs: Showing window...
}
}
class EngineWindow : IEngineWindow
{
public void Show()
{
Console.WriteLine("Showing window...");
}
}
//External assembly (dll-file)
class Testwindow : IWindow
{
public void BeforeClose()
{
Console.WriteLine("Closing...");
}
}
This sounds like you need a wrapper.
Let your internal class take an IWindow instance in its constructor
store it in a private field
implement both interfaces
and forward all IWindow members to the internal instance
Update: if you consider CastleWindsor a simpler approach, here it is (using xUnit for tests):
namespace Mixins
{
using System;
using Castle.DynamicProxy;
using Xunit;
public interface IA
{
void Do();
}
public interface IB
{
void Something();
}
public class A : IA
{
public void Do()
{
throw new NotImplementedException("A");
}
}
public class B : IB
{
public void Something()
{
throw new NotImplementedException("B");
}
}
public class Blender
{
[Fact]
public void Mix()
{
var options = new ProxyGenerationOptions();
// the instances for A and B would be the user provided and yours
options.AddMixinInstance(new A());
options.AddMixinInstance(new B());
var proxy = new ProxyGenerator().CreateClassProxy<object>(options);
Assert.IsAssignableFrom<IA>(proxy);
Assert.IsAssignableFrom<IB>(proxy);
try
{
((IA)proxy).Do();
}
catch (NotImplementedException ex)
{
if (ex.Message != "A")
{
throw;
}
}
try
{
((IB)proxy).Something();
}
catch (NotImplementedException ex)
{
if (ex.Message != "B")
{
throw;
}
}
}
}
}
I am the author of NCop - A composite-aspect framework that can help you achieve your goal.
NCop wiki
You basically need to create a new composite type interface that will implement both of your window interfaces and mark it as a composite using the TransientComposite attribute.
[TransientComposite]
public interface ICompositeWindow : IWindow, IEngineWindow
{
}
Order NCop to match between interfaces and implementations using Mixins attribute.
[TransientComposite]
[Mixins(typeof(EngineWindow), typeof(Testwindow))]
public interface ICompositeWindow : IWindow, IEngineWindow
{
}
create a CompositeContainer that will emit the new type.
class Program
{
static void Main(string[] args) {
ICompositeWindow window = null;
var container = new CompositeContainer();
container.Configure();
window = container.Resolve<ICompositeWindow>();
window.Show();
window.BeforeClose();
}
}
your final code should be:
using System;
using NCop.Composite.Framework;
using NCop.Mixins.Framework;
using NCop.Composite.Runtime;
namespace NCop.Samples
{
[TransientComposite]
[Mixins(typeof(EngineWindow), typeof(Testwindow))]
public interface ICompositeWindow : IWindow, IEngineWindow
{
}
public interface IWindow
{
void BeforeClose();
}
public interface IEngineWindow
{
void Show();
}
public class EngineWindow : IEngineWindow
{
public void Show() {
Console.WriteLine("Showing window...");
}
}
public class Testwindow : IWindow
{
public void BeforeClose() {
Console.WriteLine("Closing...");
}
}
class Program
{
static void Main(string[] args) {
ICompositeWindow window = null;
var container = new CompositeContainer();
container.Configure();
window = container.Resolve<ICompositeWindow>();
window.Show();
window.BeforeClose();
}
}
}

Need an OOP Trick

I want an abstract class that raises an event, this event will be raised by the concrete class.
What I want is when I use another class to listen to these events the signature of the delegate should have the concrete type not the abstract, I don't want to cast it.
For the moment I have come up with this solution. It works but I don't find it particularly clever especially because of the "STUPID, DOESN'T MAKE SENSE......" part.
Here is my solution :
public delegate void ClassAEventHandler<TClassA>(TClassA classA) where TClassA : ClassA;
//Abstract class that raise Event
public abstract class ClassA<TClassA> : where TClassA : ClassA
{
public event ClassAEventHandler<TClassA> onClassEventRaised;
private TClassA eventClassA;
public void registerEventClass(TClassA classA)
{
this.eventClassA = classA;
}
public void raiseClassEvent()
{
this.onClassEventRaised(this.eventClassA);
}
}
// Exemple of concrete type
public class ClassB : ClassA<ClassB> // <------ IT SEEMS DUMB
{
public void action()
{
//Do something then raise event
this.raiseClassEvent();
}
public void saySomething() {};
}
// Exemple of concrete type
public class ClassC : ClassA<ClassC> // <------ IT SEEMS DUMB
{
public void command()
{
//Do something then raise event
this.raiseClassEvent();
}
public void destroySomething() {};
}
//Class that listen to the event raised
public class MyEventListener
{
private ClassB classB;
private ClassC classC;
public MyEventListener()
{
this.classB = new ClassB();
this.classB.registerEventClass(this.classB); // <------ STUPID, DOESN'T MAKE SENSE......
this.classB.onClassEventRaised += classB_onClassEventRaised;
this.classC = new ClassC();
this.classC.registerEventClass(this.classC); // <------ STUPID, DOESN'T MAKE SENSE......
this.classC.onClassEventRaised += classC_onClassEventRaised;
}
public void classB_onClassEventRaised(ClassB classB)
{
classB.saySomething();
}
public void classC_onClassEventRaised(ClassC classC)
{
classC.destroySomething();
}
//What i don't want
/*
public void classB_onClassEventRaised(ClassA classA)
{
((classB)classA).saySomething();
}
*/
}
First of all, you're not following regular event design in .NET.
Instead of implementing your own delegate, use EventHandler<TArgs>, and create a derived class of EventArgs.
Your CustomEventArgs should have a T generic parameter:
public class CustomEventArgs<T> where T : A
{
private readonly T _instance;
public CustomEventArgs(T instance)
{
_instance = instance;
}
public T Instance { get { return _instance; } }
}
Also, don't implement a custom way of registering events. If you want to encapsulate how handlers are added to the event, you need to use event accessors.
Finally, you could implement your classes as follows:
public class A<T> where T : A
{
private event EventHandler<CustomEventArgs<T>> _someEvent;
// An event accessor acts like the event but it can't be used
// to raise the event itself. It's just an accessor like an special
// event-oriented property (get/set)
public event EventHandler<CustomEventArgs<T>> SomeEvent
{
add { _someEvent += value; }
remove { _someEvent -= value; }
}
protected virtual void RaiseSomeEvent(CustomEventArgs<T> args)
{
// If C# >= 6
_someEvent?.Invoke(this, args);
// Or in C# < 6
// if(_someEvent != null) _someEvent(this, args);
}
}
public class B : A<B>
{
public void DoStuff()
{
// It's just about raising the event accessing the whole
// protected method and give an instance of CustomEventArgs<B>
// passing current instance (i.e. this) to CustomEventArgs<T>
// constructor.
RaiseSomeEvent(new CustomEventArgs<B>(this));
}
}
Now, if you try to handle SomeEvent, you'll get the CustomEventArgs<B> typed as B instead of A:
B b = new B();
b.SomeEvent += (sender, args) =>
{
// args.Instance is B
B instance = args.Instance;
};
b.DoStuff(); // Raises SomeEvent internally

Derived types with Method overloading

The code is simple enough to understand I hope.
I'm trying to use an interface type IColor in order to pass color objects to the ColorManager. I then want the ColorManager to pass this object to the IColor object as its own type, so the method overloads gets called.
However, it seems since it is being passed as the IColor type, C# will not implicity cast it into its complete type as either a BlueColor or GreenColor.
I hope this makes some sense to somebody on what I want to achieve. Is this possible in C#?
[Solution]
http://msdn.microsoft.com/en-us/library/dd264736.aspx
Overload Resolution with Arguments of Type dynamic
My code so far:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
namespace Example
{
public interface IColor
{
void CatchColor(IColor c);
}
public class BlueColor : IColor
{
public void CatchColor(IColor c)
{
}
}
public class GreenColor : IColor
{
public void CatchColor(BlueColor c)
{
Console.WriteLine("CAUGHT BLUE!");
}
public void CatchColor(GreenColor c)
{
Console.WriteLine("CAUGHT GREEN!");
}
public void CatchColor(IColor c)
{
Console.WriteLine("CAUGHT SOME COLOR!");
}
}
public class ColorManager
{
public void PassColor(IColor c)
{
// Don't use static type-checking
// Problem solved
dynamic AnyColor = c;
AnyColor.CatchColor(AnyColor);
}
public static void Main()
{
GreenColor G = new GreenColor();
new ColorManager().PassColor(G);
Console.ReadLine();
return;
}
}
}
One possiblity to tell the ColorManager class to use the correct type of the passed object is to use an abstract class, that already implements the CatchColor:
public abstract class IColor
{
// override in every class
public abstract void PrintColor();
// has the correct type passed with the interface
public void CatchColor(IColor c)
{
c.PrintColor();
}
}
Then the sub classes need to implement only PrintColor with the correct color:
public class BlueColor : IColor
{
public override void PrintColor()
{
Console.WriteLine("BLUE!");
}
}
public class GreenColor : IColor
{
public override void PrintColor()
{
Console.WriteLine("GREEN!");
}
}
The manager is the same:
public class ColorManager
{
public void PassColor(IColor c)
{
c.CatchColor(c);
}
}
It can be used like this:
GreenColor G = new GreenColor();
var cm = new ColorManager();
cm.PassColor(G);
cm.PassColor(new BlueColor());
The outputs is:
GREEN!
BLUE!
What you want is late method binding.
The downside to this is you have to add methods for each new type of color. The upside is you don't have to maintain a case statement or conditional logic.
See here for more detail:
Early and late binding
Edit: Here is a working example of this type of late-binding.
class Program {
static void Main(string[] args) {
//Declare instances
BaseClass myClass = new Class2();
BaseClass otherClass = new Class1();
//Invoke the action method which will match based on the BaseClass type
Action(myClass);
Action(otherClass);
Console.ReadLine();
}
public static void Action(BaseClass classType) {
//Remove the compile-time type so the runtime can select the method based on signature
dynamic aClass = classType;
ServiceMethod(aClass);
}
public static void ServiceMethod(dynamic input) {
Methods(input);
}
public static void Methods(Class1 classType) {
Console.WriteLine("Class1");
Debug.WriteLine("Class1");
}
public static void Methods(Class2 classtype) {
Console.WriteLine("Class2");
Debug.WriteLine("Class2");
}
public static void Methods(Class3 classType) {
Console.WriteLine("Class3");
Debug.WriteLine("Class3");
}
}
public abstract class BaseClass { //This could also be an interface
public Guid Id { get; set; }
public string Name { get; set; }
}
public class Class1 : BaseClass {
}
public class Class2 : BaseClass{
}
public class Class3 : BaseClass {
}
So you want something like:
public void CatchColor(Color c)
{
if (c is BlueColor)
CatchColor(c as BlueColor);
if (c is GreenColor)
CatchColor(c as GreenColor);
}
?

Categories

Resources