I have been using a lot of APIs where to listen to some event I just need to implement an interface, but it doesn't require me to subscribe, how they do that?
To explain it better here is how I usually do my listeners
interface IListener
{
void OnEventHappen();
}
public class EventClass
{
public static Action onEvent;
}
public class ListenerClass : IListener
{
//constructor
public ListenerClass()
{
EventClass.onEvent += OnEventHappen;
}
//function from IListener interface
public void OnEventHappen() { //something... }
}
but in those APIs it is not necessary to subscribe anywhere, I just need to implement the interface like this: (I removed the EventClass because in those APIs I have no access to the classes who trigger the events)
interface IListener
{
void OnEventHappen();
}
public class ListenerClass : IListener
{
//function from IListener interface
public void OnEventHappen() { //something... }
}
In c# such behavior can be achieved using reflection.
One example in comments mentions Unity and it's methods like OnBeginDrag or Update. Those are not called using c# events. Unity is mostly written in c++ and after your c# code is compiled Unity looks for all classes implementing certain interfaces or inheriting from certain classes (like MonoBehaviour) and checks if they have matching methods (like Update()) so it can call them later when necessary.
Another comment mentions Photon, a networking engine commonly used with Unity. In this case there is no "magic" or even reflection. To receive Photon's callbacks you have to call PhotonNetwork.AddCallbackTarget method and pass instance of your class as an argument. Only confusing thing in case of Photon is fact, that you don't have to do that directly. Instead of calling this method yourself, you can just inherit from MonoBehaviourPunCallbacks class which implements all Photon's callback interfaces and calls PhotonNetwork.AddCallbackTarget in it's OnEnable method. That method is in turn called by Unity like I explained earlier.
Related
Ok, so working on a dotnet Core 2 console app that I'm designing to run either on Windows or *Nix. Now the the part I'm trying to figure out is I want to only have one code base and let the code determine if it's running on Win then go one path, or if on *Nix go another path.
So what I'm thinking is create an Interface with the way I want the classes for the two paths to look as far as properties and methods, then create a Win and Nix class implementing the interface.
Seems straightforward, but what I am racking my brain on is how exactly do I create the object based on the OS? I have wrapper code for "IsWindows" and "IsNix" that returns a boolean each, so my thought is to use a If statement to do this. Not sure how to create a generic global variable, then instantiate it in the conditional statement.
Maybe I'm off my rocker and trying to do something odd here, if I am I'm not afraid to be told that. My only other thought is to perform the work inside the conditional statement, but that really would negate my desire to create the object in the conditional based on the OS, then call the same code going forward, using the classes that implement the Interface to make the different code calls as appropriate.
So I feel like a complete idiot with brain lock. Simply creating an object of the type of the Interface is all I needed to do, then set it to an instance of the class in the conditional statement. Easy peasy, not sure why I had a brain fart on that one.
Having common interface and two classes implementing it for different OS'es is definitelly good approach. So let's assume you have
public interface IMyInterface
{
void DoSomething();
}
public class WinClass: IMyInterface
{
public void DoSomething()
{
//Implementation of DoSomething for Windows
}
}
public class NixClass : IMyInterface
{
public void DoSomething()
{
//Implementation of DoSomething for *nix
}
}
Common way to instantiate different implementations of interface (or abstract class) based on certain conditions is using Factory pattern. This might look like this:
public static class MyInterfaceFactory
{
public static IMyInterface CreateMyInterface()
{
if (IsWindows)
return new WinClass();
else if (IsNix)
return new NixClass();
else
throw new PlatformNotSupportedException();
}
}
This is the only platform-dependent part of your code, rest of your code will use only IMyInterface and will be platform independent. You can either use this factory whenever you need to create new instance implementing IMyInterface, or you can use Singleton pattern to ensure, that only one objects will be created for entire application:
public static class MyInterfaceSingleton
{
static MyInterfaceSingleton()
{
Instance = MyInterfaceFactory.CreateMyInterface();
}
public static IMyInterface Instance { get; private set; }
// In C# 7, you can use just this instead:
// public static IMyInterface Instance { get; } = MyInterfaceFactory.CreateMyInterface();
}
Your application then simply call MyInterfaceSingleton.Instance.DoSomething(); whenever needed, in a platform independent way.
I'm building a program that will be processing messages from various topics. Since the data on each topic is different, I need dedicated classes that consumes data from any given topic. I want to do so using a base class that handles the communicates with the messaging system, and derived classes that implement the handling of the message:
public abstract class MessageConsumer<T>
{
public void Start(){/*omitted*/}
/* Other abstract properties and methods here to support template pattern*/
}
The Start method will tell the MessageConsumer to start pulling in new message. Examples of derived classes are:
public class CreatedMessageConsumer : MessageConsumer<CreatedMessage>
{
/*Implementation omitted*/
}
public class DeletedMessageConsumer : MessageConsumer<DeletedMessage>{}
In the code snippet above, I omitted the required constructor arguments, but it's easy to imagine how a DiContainer can be useful here. I use Autofac. The registration of CreatedMessageConsumer and DeletedMessageConsumer using Autofac works well.
My problem is how to resolve all classes that derives from MessageConsumer<>.
This SO post discusses how to resolve a given derived type, but I want to resolve all types that derive from MessageConsumer. Subsequently I want to call the Start method on all of them, e.g. something like
foreach(var consumer in container.Resolve<IEnumerable<MessageConsumer<??>>())
{
consumer.Start();
}
However, because I cannot provide the generic argument, it will not compile. Any idea how to do this? I'm using Autofac 4.2.1.
If you do not care about the generic argument, (which you don't otherwise you would have specified a generic argument in your last code block), then:
Define an interface (with method Start)
Implement that on your type(s)
Add it to the As chain where you define your Autofac registrations
Resolve the new interface
Updated code:
public interface IStartable {
void Start();
}
public abstract class MessageConsumer<T> : IStartable
{
public void Start(){/*omitted*/}
/* Other abstract properties and methods here to support template pattern*/
}
Caling code:
foreach(var consumer in container.Resolve<IEnumerable<IStartable>>())
{
consumer.Start();
}
I am using SignalR in version 2.1.2. I have noticed there are two public hub classes for me to use, Hub and Hub<T>. The former has an MSDN page which appears to be outdated and the latter lacks any MSDN page at all. I believe the MSDN documentation is not up to date with the latest version of SignalR from Nuget (which I'm using), because sources decompiled with the help of ReSharper show both of the classes inherit from HubBase base class. The MSDN page's Inheritance Hierarchy section shows the Hub class as inheriting from Object and implementing IHub and IDisposable interfaces, however the decompiled sources reveal the aforementioned HubBase base class, implementing the IHub interface which in turn implements IDisposable.
The difference between the non-generic and generic variant of the classes is that the non-generic one's Clients property returns IHubCallerConnectionContext<dynamic> while the generic variant returns typed IHubCallerConnectionContext<T>.
I'd like to have my clients typed, so when I call the client methods from the hub, I'd have proper Intellisense support and strongly-typed arguments. What I struggle with, though, is how to let the Hub know that my client model's method is actually to be invoked in the browser.
This is my TestModel class:
public sealed class TestModel
{
public String Name { get; set; }
public void Notify() {}
public void NotifyComplex(TestModel model) {}
}
With the non-generic hub, I'd just call .Notify() or .Notify(new TestModel() { Name = "sth" }) on the dynamicly bound this.Context.Clients.Client(…) or this.Context.Caller, but with the generic class, when I call these empty methods in similar manner, the browser is not notified at all.
How do you use the generic hub class the way it's supposed to be used?
I've found the answer. The MSDN documentation is not up-to-date as of yet, but the ASP .NET site offers nice SignalR tutorials and one of them covers the typed hubs:
http://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-server#stronglytypedhubs
As the example in the article shows, if you use an interface for the type argument, everything works and you get strongly-typed hub clients whose methods are correctly translated to RPCs. Here's a piece of code I tested this with:
public sealed class TestHub
: Hub<ITestClient>
{
public override Task OnConnected()
{
this.Clients.Caller.SayHello("Hello from OnConnected!");
return base.OnConnected();
}
public void Hi()
{
// Say hello back to the client when client greets the server.
this.Clients.Caller.SayHello("Well, hello there!");
}
}
public interface ITestClient
{
void SayHello(String greeting);
}
What alternative can one use to avoid exposing both events and an interface.
I have a class that has a determined life cycle: created, modified, ...
clients mainly GUIs need to hook up into the life cycle of that class so the simplest way to do it is to expose events, at the same time I need to move some responsibilities -that happen during the life cycle- out of the class so I came up with this solution:
Interface ILifeCycle
{
void OnCreated(...);
void OnModified(...);
// ...
}
classA
{
private ILifeCycle lifeCycle;
/// ...
public event EventHandler Created(object sender, EventArgs args);
public event EventHandler Modified(object sender, EventArgs args);
/// ...
protected void OnCreated()
{
lifeCycle.OnCreated(...);
if(Created!=null)
Created(this,EventArgs.Empty);
}
protected void OnModified()
{
lifeCycle.OnModified(...);
if(Modified!=null)
Modified(this,EventArgs.Empty);
}
/// ...
}
Doing this I can inject a Logger that implements ILifeCycle, and so move the logging responsibility to its own class,
but it feels like it's going to be a lot of repetition.
What clean alternatives would you recommend to achieve this?
In general Interface and Events/Delegates are used for two very different kinds of approach. Lets describe them each first -
Interface: The main purpose of interface is that it enforces some functionality to all implementations of that interface. And whenever you implement it in a subclass, you override the implementation of the super class. For example -
interface IA
{
void test();
}
class A : IA
{
public void test(){
}
}
class B : A
{
public void test(){
//you can only go up by calling base.test(), but cannot move down, because you do not know whether there is an implementation down the tree or not. So you cannot call it.
}
}
class C : B
{
public void test(){
//you can only go up by calling base.test(), but cannot move down, because you do not know whether there is an implementation down the tree or not. So you cannot call it.
}
}
As you can see, with interface you can only look back but cannot look forward and assume there will be any more implementations.
Events: Events are created for a different purpose. lets just say you want to give the developers some facility to rely on some activities and do some other activities based on that activities and changes, and most importantly they will be implement this in future. The events will not depend on your implementation, they will just subscribe to it and do something based on that. Whether they exists or not, your own implementation does not change or the behavior of your own code does not changes based on them. In other words, you can only move down the tree. The base class captured the event and then propagates them down the tree.
These are the usual uses of Interface and Events and they are meant to be used that way. But its not completely impossible to code such that it will entirely depend on interface and vice versa, i.e. code entirely dependent on events but that is not the way they are meant to be.
In This Case: In your case, I am thinking you are trying to achieve a modular system that will not depend on each other but again subscribe to events. There are other architectures and patterns for this, specially IOC containers will be a very helpful for you, that will entirely be interface dependent, you will not need events. Some .net IOC containers are AutoFac, Castle.Windsor, MEF
I myself, like MEF the most, here is a post on MEF that I wrote few years back, shows you how you can inject run-time handlers inside a container -
http://mahmudulislam.me/2012/04/20/1a-managed-extensibility-framework-introduction/
BTW, article is a bit old, I am working on updating this one.
Solution with IOC: I am giving a probable solution with MEF -
Interface ILifeCycle
{
void OnCreated(...);
void OnModified(...);
...
}
[Export(typeof(ILifeCycle))] //export our classes for injection
classB : ILifeCycle{
public void OnCreated(...)
{
....
}
public void OnModified(...){
}
}
[Export(typeof(ILifeCycle))] //export our classes for injection
classC : ILifeCycle{
public void OnCreated(...)
{
....
}
public void OnModified(...){
}
}
classA
{
[ImportMany] //get all exported classes for injection
private IList<ILifeCycle> _observers;
protecetd void OnCreated()
{
//use MEF to build composition and then do the following
foreach(var o in _observers){
o.OnCreated(...);
}
}
protecetd void OnModified()
{
//use MEF to build composition and then do the following
foreach(var o in _observers){
o.OnModified(...);
}
}
...
}
This is a very basic solution. But in your case you might wanna make use of asynchronous programming. Because there is very big difference between Events and Interfaces. By default, events handlers are call in a separate thread and thus it does not halt the caller, but interface implement will hang the caller until the method finishes. So make sure you use asynchronous programming to not block your main process.
Asynchronous Programming with Async and Await (C# and Visual Basic)
I'm not sure I understood you well but I think you worry about repetitions in different types implementing ILifeCycle. So, you can take advantage of inheritance:
abstract class LifeCycleBase
{
public void OnCreated(...)
{
.....
}
public void OnModified(...);
{
.....
}
...
}
class LifeCycleLoger : LifeCycleBase
{
public void OnCreated(...)
{
....
base.OnCreate();
}
....
}
I'm porting a C# library to COM and I'm having a hard time trying to translate some delegates. The C# library works with some callbacks (using delegates). Usually I would translate that to events to be consumed by COM clients but the library only makes public Interfaces so I can not use the ComSourceInterfaces.
As an example of what I would like to be able to do:
[ComVisible(false)]
public delegate void ReceivedCOMMessageHandler (MessageCOM^ message);
[ComSourceInterfaces("ReceivedMessageEventInterface")]
public interface class IChannelCOM
{
bool PushMessage (MessageCOM^ message);
bool RegisterEventHandler (ReceivedCOMMessageHandler^ handler, FilterCOM^ filter);
bool UnRegisterEventHandler (ReceivedCOMMessageHandler^ handler);
property String^ Name;
event ReceivedCOMMessageHandler^ ReceivedMessage;
};
[InterfaceType(ComInterfaceType::InterfaceIsIDispatch)]
[Guid("D4D2A638-303E-41d4-8925-07A2A60B17F3")]
public interface class ReceivedMessageEventInterface
{
[DispId(1)] void ReceivedMessage(MessageCOM^ message);
};
I can't do this because the event is declared on a interface and the ComSourceInterface can only be declared in a class.
Any hints on what can I do to solve this problem?
EDIT: Another way of saying the same. Is there a way to declare events in interfaces rather than in classes in COM?
Thanks in advance.
As far as I've seen there is no way of doing that other than with Events and Events can only be thrown from a Class never from an Interface.