implementing delegate in interface - c#

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();
}
}

Related

How to implement a non-generic interface and call with generic

Probably a bad title, but I am trying to abstract away the type "EventHub" from my generic Handler class.
I would like to inject a function instead into my subscribe method to decouple the two types. Unfortunately, the only way I can see doing this is if I make my IHandler a generic, but this causes other problems.
Is there a design pattern to decouple these two types? Commented out are lines that I would like in some way.
public interface IHandler
{
//void Subscribe(Func<Action<T>, Guid> subscribe);
void Subscribe(EventHub eventHub);
void Unsubscribe(Action<Guid> action);
}
public abstract class Handler<T> : IHandler
{
private Guid _subscriptionToken;
public virtual void Subscribe(EventHub eventHub)
{
var action = new Action<T>(Handle);
_subscriptionToken = eventHub.Subscribe(action);
}
/*public virtual void Subscribe(Func<Action<T>, Guid> subscribe)
{
var action = new Action<T>(Handle);
_subscriptionToken = subscribe(action);
}*/
public virtual void Unsubscribe(Action<Guid> action)
{
action(_subscriptionToken);
}
public abstract void Handle(T eventType);
}
Thanks for the help!
internal interface IHandler
{
void Subscribe(Func<Action<object>, Guid> subscribe);
void Unsubscribe(Action<Guid> action);
}
public abstract class Handler<T> : IHandler
{
private Guid _subscriptionToken;
public virtual void Subscribe(Func<Action<object>, Guid> subscribe)
{
var action = new Action<T>(HandleNonAsync);
_subscriptionToken = subscribe(Convert(action));
}
public virtual void Unsubscribe(Action<Guid> action)
{
action(_subscriptionToken);
}
public abstract Task HandleAsync(T eventType);
private void HandleNonAsync(T eventType)
{
HandleAsync(eventType).GetAwaiter().GetResult();
}
private Action<object> Convert(Action<T> myActionT)
{
if (myActionT == null) return null;
else return new Action<object>(o => myActionT((T)o));
}
}

MS unity container

I have an interface IInterface and it looks something like below -
public interface IInterface
{
void SomeMethod1();
void SomeMethod2();
void SomeMethod3();
.
.
.
}
One of the implementations is something like -
public class Implementation : IInterface
{
private Object obj;
public Implementation(Object obj)
{
this.obj = obj;
// Do Something
}
public void SomeMethod1()
{
lock(obj)
{
// Do Something
}
}
public void SomeMethod2()
{
// Do Something
}
public void SomeMethod3()
{
lock(obj)
{
// Do Something
}
}
.
.
.
}
How to pass a static readonly instance of type Object while registering Implementation class with type IInterface via unity configuration?
My preferred approach is probably to create a factory for creating IInterfaces
public interface IInterface
{
void SomeMethod1();
}
public interface IInterfaceFactory
{
IInterface CreateInterface();
}
public class StandardInterfaceFactory : IInterfaceFactory
{
// Define your static lock object here. Other customers
// can define their own IInterfaceFactory to use a
// different lock object.
private static readonly object lockObject = new object();
public IInterface CreateInterface()
{
return new StandardInterface(lockObject);
}
}
public class StandardInterface : IInterface
{
private readonly object lockObject;
public StandardInterface(object lockObject)
{
this.lockObject = lockObject;
}
public void SomeMethod1()
{
lock (this.lockObject)
{
Console.WriteLine("I've locked on " + lockObject);
}
}
}
Your unity configuration and client code will then look like this.
void Main()
{
IUnityContainer container = new UnityContainer();
// This mapping can be done trivially in XML configuration.
// Left as an exercise for the reader :)
container.RegisterType<IInterfaceFactory, StandardInterfaceFactory>();
IInterfaceFactory factory = container.Resolve<IInterfaceFactory>();
IInterface myInterface = factory.CreateInterface();
myInterface.SomeMethod1();
}

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);
}
?

Can I create a delegate for the entire class c#

I have used delegates to represent methods - but I now have many classes that have same methods (but different code in those methods).
Is there a way to delegate the entire class?
Pseudo code:
class myModelA
{
void update()
{
}
}
class myModelB
{
void update()
{
}
}
delegate class myModel;
if (x==1)
myModel = myModelA;
else
myModel = myModelB;
myModel.update();
I know I can delegate the "üpdate" method BUT in real world I have lots of methods and I would rather just simply delegate the class.
EDIT1 based on Jon Skeet's answer
BUT how do I declare a public variable? (non public variables compile OK)
public interface IModel
{
double myDouble; <<<< this gives an error
void Update();
}
public class MyModelA : IModel
{
public double myDouble;
public void Update() { ... }
}
public class MyModelB : IModel
{
public double myDouble;
public void Update() { ... }
}
No, in this case you don't want a delegate - you want an interface.
You create an interface which all of your classes implement:
public interface IModel
{
void Update();
}
public class MyModelA : IModel
{
public void Update() { ... }
}
public class MyModelB : IModel
{
public void Update() { ... }
}
Then:
IModel model;
if (x == 1)
{
model = new MyModelA();
}
else
{
model = new MyModelB();
}
model.Update();
As Jon Skeet, I think you need to use interfaces.
A little changed code from
http://www.dotnetperls.com/interface
using System;
interface IPerl
{
void Read();
}
class TestA : IPerl
{
public void Read()
{
Console.WriteLine("Read TestA");
}
}
class TestB : IPerl
{
public void Read()
{
Console.WriteLine("Read TestB");
}
}
class Program
{
static void Main()
{
IPerl perl = new TestA(); // Create instance.
perl.Read(); // Call method on interface.
}
}

Cannot add object to list

I'm trying out an example of using Domain Events to notify of when something has happened in a system (borrowed from here and here).
I'm really close to getting the code working how I want, however, I've hit a bit of a brick wall. Here is my DomainEvents class:
public static class DomainEvents
{
[ThreadStatic]
private static IList<IEventHandler<IDomainEvent>> Actions;
public static void Register<T>(IEventHandler<T> callback) where T : IDomainEvent
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback); // <---- Problem here, since I can't add callback to the collection.
}
public static void ClearCallbacks()
{
Actions = null;
}
public static void Raise<T>(T args) where T : IDomainEvent
{
if (Actions == null)
{
return;
}
foreach (var action in Actions)
{
if (action is IEventHandler<T>)
{
((IEventHandler<T>)action).Handle(args);
}
}
}
The above won't compile because Actions.Add cannot accept callback since it's a IEventHandler<T> type rather then a IEventHandler<IDomainEvent> type. Here's some more code to clarify.
This is called from my console application:
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
CustomerHasUnpaidDuesEventHandler implements IEventHandler<CustomerHasUnpaidDuesEvent>, where CustomerHasUnpaidDuesEvent implements IDomainEvent.
public class CustomerHasUnpaidDuesEventHandler : IEventHandler<CustomerHasUnpaidDuesEvent>
{
public IEmailSender EmailSender { get; set; }
public void Handle(CustomerHasUnpaidDuesEvent #event)
{
this.EmailSender.SendEmail(#event.Customer.EmailAddress);
}
}
public class CustomerHasUnpaidDuesEvent : IDomainEvent
{
public CustomerHasUnpaidDuesEvent(Customer customer)
{
this.Customer = customer;
}
public Customer Customer { get; set; }
}
This is what I don't get - if CustomerHasUnpaidDuesEvent implements IDomainEvent, then why is the call to Actions.Add failing? How can I resolve this?
EDIT:
To make things clearer, here is entire code for my test app:
class Program
{
static void Main()
{
DomainEvents.Register(new CustomerHasUnpaidDuesEventHandler());
var c = new Customer();
c.EmailAddress = "test#dfsdf.com";
c.CheckUnpaidDues();
}
}
public interface IEventHandler<in T> where T : IDomainEvent
{
void Handle(T args);
}
public interface IEmailSender
{
void SendEmail(string emailAddress);
}
public interface IDomainEvent
{
}
public static class DomainEvents
{
[ThreadStatic]
private static IList<IEventHandler<IDomainEvent>> Actions;
public static void Register<T>(IEventHandler<T> callback) where T: IDomainEvent
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback);
}
public static void ClearCallbacks()
{
Actions = null;
}
public static void Raise<T>(T args) where T : IDomainEvent
{
if (Actions == null)
{
return;
}
foreach (IEventHandler<T> action in Actions)
{
(action).Handle(args);
}
}
}
public class CustomerHasUnpaidDuesEventHandler : IEventHandler<CustomerHasUnpaidDuesEvent>
{
public IEmailSender EmailSender { get; set; }
public void Handle(CustomerHasUnpaidDuesEvent #event)
{
this.EmailSender.SendEmail(#event.Customer.EmailAddress);
}
}
public class CustomerHasUnpaidDuesEvent : IDomainEvent
{
public CustomerHasUnpaidDuesEvent(Customer customer)
{
this.Customer = customer;
}
public Customer Customer { get; set; }
}
public class Customer
{
public string Name { get; set; }
public string EmailAddress { get; set; }
public bool HasUnpaidDues { get; set; }
public void CheckUnpaidDues()
{
HasUnpaidDues = true;
DomainEvents.Raise(new CustomerHasUnpaidDuesEvent(this));
}
}
Cheers.
Jas.
There is no need for your Register method to be generic:
public static void Register(IEventHandler<IDomainEvent> callback)
{
if (Actions == null)
{
Actions = new List<IEventHandler<IDomainEvent>>();
}
Actions.Add(callback);
}
Edit:
The problem is that in order to have IEventHandler<CustomerHasUnpaidDuesEvent> to be in the list of IEventHandler<IDomainEvent>s, we need T to be a covariant template parameter in IEventHandler<T> (which is declared as IEventHandler<out T>). However in order to allow the function Handle(T arg), we need T to be contravariant. So strictly this way won't work. Imagine: if we really could insert an IEventHandler<CustomerHasUnpaidDuesEvent> into a list of IEventHandler<IDomainEvent>s, than someone might try to call Handle with the argument of some type which derives from IDomainEvent but is not a CustomerHasUnpaidDuesEvent! This should be impossible to do.
The solution is that we don't need the exact type at Register, so we can keep a reference to a generic base interface. The implementation is here: http://ideone.com/9glmQ
Old answer is not valid, kept below for consistency.
Maybe you need to declare IEventHandler to accept T as a covariant type?
interface IEventHandler<in T> where T: IDomainEvent
{
void Handle();
// ...
}
Edit: surely CustomerHasUnpaidDuesEvent is an IDomainEvent, but you need IEventHandler<CustomerHasUnpaidDuesEvent> to be a IEventHandler<IDomainEvent>. This is exactly what covariance does. In order to allow that, your template parameter in IEventhandler must be declared covariant (<in T> instead of just <T>).

Categories

Resources