I am trying to add webapi (owin.selfhosting) support to existing C# console app and I have problem with callbacks from the controller. Essentially I need to call a function as a reaction to the http request. I think it's possible with delegates/events, but so far no success.
Update:
Using static event seems to work, I used a standard pattern as described in this video (https://www.youtube.com/watch?v=jQgwEsJISy0) and adding a static keyword before event declaration. But mixing static delegate with non static subscriber probably is not the best practice.
Code sample :
//appcontroller.cs
public class AppController : ApiController
{ public delegate void EventHandler(object source, EventArgs args);
public static event EventHandler EventRecived;
protected virtual void OnEventRecived(string arg)
{
if( EventRecived != null)
{
EventRecived(this, arg);
}
}
[Route("api/{arg}")]
public void GetFoo(string arg)
{
/*
*
*/
OnEventRecived();
}
}
//program.cs
class Program
{ static void Main(string[] args)
{ WebApp.Start<Startup>(url: baseAddress);
SomeClass obj = new SomeClass();
AppController.EventHandler+=obj.OnRecivedEvent;
while (true)
{ //do work
}
}
}
class SomeClass
{ public SomeClass() {}
public void OnRecivedEvent(object sender, EventArgs e)
{
Foo(e);
}
public void Foo(string arg)
{
//do something
Console.WriteLine("request of "+arg);
}
}
Example for http get request to http://localhost:8080/api/holy_grail
Console output >>request of holy_grail
Related
I want to implement delegation pattern using delegates
public class Cat {
private delegate void SoundDelegate();
private SoundDelegate sound;
public Cat() {
sound = new SoundDelegate(SomeClass.DoSound1);
}
public void DoSound() {
sound();
}
}
public class PussyCat {
private delegate void SoundDelegate();
private SoundDelegate sound;
public PussyCat() {
sound = new SoundDelegate(SomeClass.DoSound2);
}
public void DoSound() {
sound();
}
}
public class SomeClass {
public static void DoSound1() {
Console.WriteLine("Sound 1");
}
public static void DoSound2() {
Console.WriteLine("Sound 2");
}
}
Does this code impelement the delegation pattern? I mean can I use delegates for implement delegation pattern or this way is incorrect.
And if the previous example is correct and I can use delegates to implement the delegation pattern and implement the observer pattern, then what is the difference between the observer pattern and the delegation pattern and what is similar?
The difference between delegation and observer patterns is a level of control your class has over the delegate/observer.
In case of delegate, it's assumed that your class has full control over how delegated class should be used. The observable class has no idea of how exactly it would be used by other classes.
It's also often assumed that observable class could have any number of observers while delegate is usually one.
I also simplified the code provided trying to avoid unnecessarily class PussyCat, so the original class could be configured to use any delegate in runtime.
You can also find CatObservable class to understand the idea of observable-observer implementation.
class Program
{
static void Main(string[] args)
{
Cat cat1 = new Cat(SomeClass.DoSound1);
Cat cat2 = new Cat(SomeClass.DoSound2);
CatObservable cat3 = new CatObservable();
cat3.Sound += Cat3_Sound;
cat3.Sound += (object sender, EventArgs e) => { SomeClass.DoSound1(); } ;
cat3.Sound += (object sender, EventArgs e) => { SomeClass.DoSound2(); };
}
private static void Cat3_Sound(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
public class Cat
{
public delegate void SoundDelegate();
public SoundDelegate Sound { get; set; }
public Cat(SoundDelegate soundDelagate)
{
Sound = soundDelagate;
}
protected void DoSound()
{
if (Sound!=null)
Sound();
}
}
public class CatObservable
{
public event EventHandler Sound;
public CatObservable()
{
}
protected void DoSound()
{
if (Sound != null)
Sound(this, EventArgs.Empty);
}
}
public class SomeClass
{
public static void DoSound1()
{
Console.WriteLine("Sound 1");
}
public static void DoSound2()
{
Console.WriteLine("Sound 2");
}
}
I'm trying to create a class (in the context of a Windows Application) that can update progress (or send some user message) back to the main form UI via delegates. The problem I have is that the compiler won't allow any of the constructs I attempt because of missing object references. This has been discussed here but no answers had to do with writing to an object on a Form.
in c++ I would do this:
void LogToUI(string s)
{
if(Form1)
Form1->update(s);
}
void TForm1::update(string s)
{
listbox->Items->Add(s);
}
// so that any function, anywhere, can update the listbox (thread safety aside)
in C#:
namespace test
{
public delegate void callback(String msg);
public partial class Form1 : Form
{
public void writeToListbox(String s)
{
listbox.Items.Add(s);
}
public static void writeToConsole(String s)
{
System.Console.WriteLine(s);
}
public void createclass
{
callback ui_update = writeToConsole; // this is ok
callback ui_update = writeToListbox; // not allowed
someclass SC = new someclass(ui_update);
}
}
class someclass
{
callback cb;
void someclass(callback T)
{
this.cb = T;
}
void logthis(string s)
{
cb("it's me!");
}
}
}
I understand the problem with having to assign a static method to the delegate, and the Form1 method is non-static. I would like to use the delegate method because it seems the cleanest; I just can't find a way to write this in such a way as to make it work, short of passing a pointer back to the Form, which seems messy.
I believe I just came across the answer. You have to expose a static reference to a UI object, in this case a ListBox. Then you can assign the callback delegate to a function that makes sure the listbox reference is not null. You just need to make sure you assign the static reference when the form is created:
namespace test
{
public delegate void callback(String msg);
public partial class Form1 : Form
{
public static ListBox callbackListBox; // add this
public void writeToListbox(String s)
{
if(null == callbackListBox)return; // add this check
// also make this threadsafe:
if (callbackListBox.InvokeRequired)
{
callbackListBox.Invoke(new MethodInvoker(() => { writeToListbox(s); }));
}else{
callbackListBox.Items.Add(s);
callbackListBox.TopIndex = callbackListBox.Items.Count - (callbackListBox.Height / callbackListBox.ItemHeight);
}
}
public static void writeToConsole(String s)
{
System.Console.WriteLine(s);
}
public void createclass
{
callback ui_update = writeToListbox; // now OK
someclass SC = new someclass(ui_update);
}
// and add this to the form's constructor:
public Form1()
{
InitializeComponent();
callbackListBox = listbox1;
}
}
class someclass
{
callback cb;
void someclass(callback T)
{
this.cb = T;
}
void logthis(string s)
{
cb("it's me!");
}
}
}
I still have to try this, but at least the compiler is not complaining.
I would not be surprised if this has been answered somewhere, the problem is I am not sure how to phrase a search to find what I need. The things I have already found have either been too simplistic to be usable or poorly explained such that I cannot translate it into my own project. I had no formal instruction with event handlers, delegates, and the like (heck, I didn't even learn about Entity-Component Systems--or other design patterns--until long after I graduated college and was already employed as a programmer, and even then it wasn't something I learned at, or for, my job).
Essentially what I want to know is, what does the definition of Array.Sort<T>(T[] array, Comparison<T> comparison) look like?
There's clearly some kind of generalization going on, as myCompareDelegate(...) takes two arguments of any type. In almost everything I've found relating to Func arguments, a Func<> parameter requires explicitly declared types, with the exception of some sample code using an operator I am unfamiliar with:
SomeUtility(arg => new MyType());
public void SomeUtility<T>(Func<object, T> converter) {
var myType = converter("foo");
}
It compiles but I have no idea what it does and as such, I do not know how to utilize it to create code that will run or do what I want to do.
My goal here is to be able to create an event system (yes, I'm aware that C# has an event system built in, but again, all the sample code I've seen is either simplified to the point of uselessness--listeners contained in the same class as the dispatcher--or complicated and unexplained). I want the following to be true:
a single function to register an event listener (for any Type of event and its subtypes)
a single function to dispatch an event (calling only the relevant listeners)
to be able to create new event types without having to modify the functions for registration and handling (no explicit types in the dispatcher beyond the base event class) provided the new event type extends the allowable event type (i.e. an Entity will only dispatch EntityEvents not WorldEvents).
I have a system that works currently, but it requires that all my handlers pass through a single "onEvent" function which takes a base event object and figures out what it's actual type is, passing that off to the true handler.
Eg:
//Entity implements IEventDispatcher
public SomeConstructor(Entity ent) {
//public delegate void EventListener(EventBase eventData); is declared
//in the IEventDispatcher interface.
ent.attachEvent(typeof(EntityEventPreRender), new EventListener(onEvent));
ent.attachEvent(typeof(EntityEventPostRender), new EventListener(onEvent));
}
//EntityEventPreRender extends EntityEventRender extends EntityEvent extends EventBase
//EntityEventPostRender extends EntityEventRender extends EntityEvent extends EventBase
public void onEvent(EventBase data) {
if(data is EntityEventPreRender)
onPre((EntityEventPreRender)data);
if(data is EntityEventPostRender)
onPost((EntityEventPostRender)data);
}
public void onPre(EntityEventPreRender evt) {}
public void onPost(EntityEventPostRender evt) {}
attachEvent() here is a function that takes a Type (used as a HashMap key) and a Delegate and stores it in a list (the HashMap value). Dispatching the event just needs to pass the EventData object, which is queried for its type (via evt.GetType()) to retrieve the list of listeners, then invoking them: listItem(evt)
But I'd rather be able to just do this:
public SomeConstructor(Entity ent) {
ent.attachEvent(onPre);
ent.attachEvent(onPost);
}
public void onPre(EntityEventPreRender evt) {}
public void onPost(EntityEventPostRender evt) {}
But I cannot, for the life of me, figure out how to do this because I do not know how to declare the attachEvent() function to take a generic function parameter the way Array.Sort<T>(T[] array, Comparison<T> comparison) does. I get the error:
"The type arguments for method doSomething<T>(SomeClass.Thing<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly."
I think you might be looking for something like the following:
public static class PubSub<TMessage>
{
private static List
<
Action
<
TMessage
>
> listeners = new List<Action<TMessage>>();
public static void Listen(Action<TMessage> listener)
{
if (listener != null) listeners.Add(listener);
}
public static void Unlisten(Action<TMessage> listener)
{
if (listeners.Contains(listener)) listeners.Remove(listener);
}
public static void Broadcast(TMessage message)
{
foreach(var listener in listeners) listener(message);
}
}
In the above code, using PubSub and specifying a type for TMessage creates a new static class in memory with its own memory space allocated for storing a separate list of listeners. The compiler will ensure that only the substituted type for TMessage and its subclasses will be allowed in that list, provided you consistently use the base type as the type argument for the TMessage type parameter.
You would then use it like so:
public class SomeMessageType
{
public int SomeId;
public string SomeDescription;
}
public class SomePublisher
{
public void DoSomethingCool(string description)
{
var randomizer = new Random();
...
PubSub<SomeMessageType>.Broadcast(new SomeMessageType(){SomeId = randomizer.Next(), SomeDescription = description});
}
}
public class SomeListener
{
static SomeListener()
{
PubSub<SomeMessageType>.Listen(SomeMessageEvent);
}
private static void SomeMessageEvent(SomeMessageType message)
{
// do something with the message
}
}
If you then create another class SomeOtherMessageType which does not inherit from SomeMessageType and make similar calls to it, it will only broadcast to listeners of that specific type.
EDITED:
Here is a full proof of concept that compiles that you can run in a console app to allay any remaining concerns you may have over efficacy of this technique.
using System;
using System.Collections.Generic;
namespace TestPubSub
{
public class Program
{
public static void Main(string[] args)
{
Program.startListeners();
Program.sendTestMessages();
Program.stopConsoleFromExitingImmediately();
}
private static void startListeners()
{
SomeListener.Listen();
SomeOtherListener1.Listen();
SomeOtherListener2.Listen();
}
private static void sendTestMessages()
{
var publisher1 = new SomePublisher();
var publisher2 = new SomeOtherPublisher();
publisher1.DoSomethingCool("Hello world");
publisher2.DoSomethingElse(DateTime.Now);
}
private static void stopConsoleFromExitingImmediately()
{
Console.ReadKey();
}
}
public static class PubSub<TMessage>
{
private static List
<
Action
<
TMessage
>
> listeners = new List<Action<TMessage>>();
public static void Listen(Action<TMessage> listener)
{
if (listener != null) listeners.Add(listener);
}
public static void Unlisten(Action<TMessage> listener)
{
if (listeners.Contains(listener)) listeners.Remove(listener);
}
public static void Broadcast(TMessage message)
{
foreach(var listener in listeners) listener(message);
}
}
public class SomeMessageType
{
public int SomeId;
public string SomeDescription;
}
public class SomeOtherMessageType
{
public DateTime SomeDate;
public Double SomeAmount;
}
public class SomePublisher
{
public void DoSomethingCool(string description)
{
var randomizer = new Random();
PubSub<SomeMessageType>.Broadcast(new SomeMessageType(){SomeId = randomizer.Next(), SomeDescription = description});
}
}
public class SomeOtherPublisher
{
public void DoSomethingElse(DateTime when)
{
var randomizer = new Random();
PubSub<SomeOtherMessageType>.Broadcast(new SomeOtherMessageType(){SomeAmount = randomizer.NextDouble(), SomeDate = when});
}
}
public class SomeListener
{
public static void Listen()
{
PubSub<SomeMessageType>.Listen(SomeMessageEvent);
}
private static void SomeMessageEvent(SomeMessageType message)
{
Console.WriteLine("Attention! SomeMessageType receieved by SomeListener with\r\nid: {0}\r\ndescription: {1}\r\n", message.SomeId, message.SomeDescription);
}
}
public class SomeOtherListener1
{
public static void Listen()
{
PubSub<SomeOtherMessageType>.Listen(SomeMessageEvent);
}
private static void SomeMessageEvent(SomeOtherMessageType message)
{
Console.WriteLine("Heads up! SomeOtherMessageType receieved by SomeOtherListener1 with\r\namount: {0}\r\ndate: {1}\r\n", message.SomeAmount, message.SomeDate);
}
}
public class SomeOtherListener2
{
public static void Listen()
{
PubSub<SomeOtherMessageType>.Listen(SomeMessageEvent);
}
private static void SomeMessageEvent(SomeOtherMessageType message)
{
Console.WriteLine("Yo! SomeOtherMessageType receieved by SomeOtherListener2 withr\namount: {0}\r\ndate: {1}\r\n", message.SomeAmount, message.SomeDate);
}
}
}
EDITED AGAIN (Alternate proof of concept using an instance based pubs):
Here is a proof of concept using an instance based PubSub.
using System;
using System.Collections.Generic;
namespace TestPubSub
{
public class Program
{
private static PubSub<SomeMessageType> pubSub1 = new PubSub<SomeMessageType>();
private static PubSub<SomeOtherMessageType> pubSub2 = new PubSub<SomeOtherMessageType>();
private static SomeListener listener1 = new SomeListener();
private static SomeOtherListener1 listener2 = new SomeOtherListener1();
private static SomeOtherListener2 listener3 = new SomeOtherListener2();
public static void Main(string[] args)
{
Program.startListeners();
Program.sendTestMessages();
Program.stopConsoleFromExitingImmediately();
}
private static void startListeners()
{
Program.listener1.Listen(Program.pubSub1);
Program.listener2.Listen(Program.pubSub2);
Program.listener3.Listen(Program.pubSub2);
}
private static void sendTestMessages()
{
var publisher1 = new SomePublisher(Program.pubSub1);
var publisher2 = new SomeOtherPublisher(Program.pubSub2);
publisher1.DoSomethingCool("Hello world");
publisher2.DoSomethingElse(DateTime.Now);
}
private static void stopConsoleFromExitingImmediately()
{
Console.ReadKey();
}
}
public class PubSub<TMessage>
{
private List
<
Action
<
TMessage
>
> listeners = new List<Action<TMessage>>();
public void Listen(Action<TMessage> listener)
{
if (listener != null) this.listeners.Add(listener);
}
public void Unlisten(Action<TMessage> listener)
{
if (listeners.Contains(listener)) this.listeners.Remove(listener);
}
public void Broadcast(TMessage message)
{
foreach(var listener in this.listeners) listener(message);
}
}
public class SomeMessageType
{
public int SomeId;
public string SomeDescription;
}
public class SomeOtherMessageType
{
public DateTime SomeDate;
public Double SomeAmount;
}
public class SomePublisher
{
private PubSub<SomeMessageType> pubSub;
public SomePublisher(PubSub<SomeMessageType> pubSub) { this.pubSub = pubSub; }
public void DoSomethingCool(string description)
{
var randomizer = new Random();
this.pubSub.Broadcast(new SomeMessageType(){SomeId = randomizer.Next(), SomeDescription = description});
}
}
public class SomeOtherPublisher
{
private PubSub<SomeOtherMessageType> pubSub;
public SomeOtherPublisher(PubSub<SomeOtherMessageType> pubSub) { this.pubSub = pubSub; }
public void DoSomethingElse(DateTime when)
{
var randomizer = new Random();
this.pubSub.Broadcast(new SomeOtherMessageType(){SomeAmount = randomizer.NextDouble(), SomeDate = when});
}
}
public class SomeListener
{
public void Listen(PubSub<SomeMessageType> pubSub)
{
pubSub.Listen(this.SomeMessageEvent);
}
private void SomeMessageEvent(SomeMessageType message)
{
Console.WriteLine("Attention! SomeMessageType receieved by SomeListener with\r\nid: {0}\r\ndescription: {1}\r\n", message.SomeId, message.SomeDescription);
}
}
public class SomeOtherListener1
{
public void Listen(PubSub<SomeOtherMessageType> pubSub)
{
pubSub.Listen(this.SomeMessageEvent);
}
private void SomeMessageEvent(SomeOtherMessageType message)
{
Console.WriteLine("Heads up! SomeOtherMessageType receieved by SomeOtherListener1 with\r\namount: {0}\r\ndate: {1}\r\n", message.SomeAmount, message.SomeDate);
}
}
public class SomeOtherListener2
{
public void Listen(PubSub<SomeOtherMessageType> pubSub)
{
pubSub.Listen(this.SomeMessageEvent);
}
private void SomeMessageEvent(SomeOtherMessageType message)
{
Console.WriteLine("Yo! SomeOtherMessageType receieved by SomeOtherListener2 withr\namount: {0}\r\ndate: {1}\r\n", message.SomeAmount, message.SomeDate);
}
}
}
I'm trying to implement EventArgs to pass a list of parameters to my messaging system: Question.
I subclassed EventArgs:
public class SingleParameterArgs<T> : EventArgs
{
public T arg1;
public SingleParameterArgs(T _arg1)
{
arg1 = _arg1;
}
}
Here's the class and method that should accept the EventArgs:
static public class Messenger<TEventArgs> where TEventArgs : EventArgs {
private static Dictionary< string, EventHandler<TEventArgs> > eventTable = new Dictionary< string, EventHandler<TEventArgs> >();
static public void Invoke(string eventType, TEventArgs args) {
EventHandler<TEventArgs> eventHandler;
if (eventTable.TryGetValue(eventType, out eventHandler)) {
if (eventHandler != null)
eventHandler();
}
}
}
Before implementing EventArgs I would invoke a message in the following way:
Messenger<GameEndingType>.Invoke( "end game", GameEndingType.TimeEnded );
But now it looks much longer and much more complicated:
Messenger< SingleParameterArgs<GameEndingType> >.Invoke( "end game", new SingleParameterArgs<GameEndingType>(GameEndingType.TimeEnded) );
Is it possible to make it look shorter? I don't want to type such a long line every time I need to send a message. Maybe I could create a wrapper?
Something like this would be perfect:
Messenger.Invoke("end game", GameEndingType.TimeEnded);
What is the best way to create a uniform wrapper for a random amount of parameters?
Are you happy for your Messenger class to be tied to SingleParameterArgs<T>? If so, you could use:
// Here TEventArgs represents the element type *within* SingleParameterArgs
public static class Messenger<TEventArgs> {
private static
Dictionary<string, EventHandler<SingleParameterArgs<TEventArgs>> eventTable =
new Dictionary<string, EventHandler<SingleParameterArgs<TEventArgs>>();
public static void Invoke(string eventType, TEventArgs args) {
EventHandler<SingleParameterArgs<TEventArgs>> eventHandler;
if (eventTable.TryGetValue(eventType, out eventHandler)) {
if (eventHandler != null) {
eventHandler();
}
}
}
}
Of course you can have both, with a totally general Messenger class (as per your question), and then a SingleParameterMessenger class which delegates to it:
public static class SingleParameterMessenger<TEventArgs> {
public static void Invoke(string eventType, TEventArgs args) {
Messenger<SingleParameterArgs<TEventArgs>>.Invoke(eventType, args);
}
}
Just as an aside, I'm not really sure this is all a good idea anyway - particularly in terms of static registration, which tends to make testing harder, and certainly needs more care in terms of concurrency. (Your code is currently not threadsafe.)
I want to use event itself in my method. Is it possible?
Can "PlayWithEvent" method use "EventSource.Test" event as parameter?
public class EventSource
{
public event EventHandler Test;
}
class Program
{
static void Main(string[] args)
{
EventSource src = new EventSource ();
PlayWithEvent (src.Test);
}
static void PlayWithEvent (EventHandler e)
{
e (null, null);
}
}
I want a syntax something like that:
class Program
{
static void Main(string[] args)
{
EventSource src = new EventSource ();
PlayWithEvent (src.Test);
}
static void PlayWithEvent (event e)
{
e += something;
}
}
Your code won't compile—you can only access the EventHandler delegate for the event from within the same class as the event, and even then it would be null unless you actually add an event handler to call.
It is not currently working because you marked
public event EventHandler Test;
as an event.
Remove the event tag and try again. It now works for me. The reason for this are the restrictions that C# has for events... But in your code, all you want is a delegate. Declare your class as:
public class EventSource
{
public EventHandler Test;
}
Note that I removed event:
public EventHandler Test;
You can't do it like that. You need to pass the actual class.
public class EventSource
{
public event EventHandler Test;
public void TriggerEvent()
{
Test(this, EventArgs.Empty);
}
}
class Program
{
static void Main(string[] args)
{
EventSource src = new EventSource ();
PlayWithEvent (src);
}
static void PlayWithEvent (EventSource e)
{
src.TriggerEvent();
}
}
You can do it in a more generic way by introducing an interface:
public interface IEventPublisher<T> where T : EventArgs
{
public void Publish(T args);
}
public class EventSource : IEventPublisher<EventArgs>
{
public event EventHandler Test;
public void Publish(EventArgs args)
{
Test(this, args);
}
}
class Program
{
static void Main(string[] args)
{
EventSource src = new EventSource ();
PlayWithEvent (src);
}
static void PlayWithEvent (IEventPublisher<EventArgs> publisher)
{
publisher.Publish(EventArgs.Empty);
}
}
Only the class that an event is defined on can raise the event. If you need other classes to be able to manipulate it, you'll have to use a regular delegate.
Note, however, that since Test resolves to the underlying delegate when used within the scope of EventSource (as opposed to the externally accessible event), EventSource can pass it as a parameter to an external method.