I am starting to learn C# and can not figure out how to call base class method from within interface method. In this particular case, I need to somehow call sendData from within onRecievemethod.
WebSocketBase.cs
using WebSocketSharp;
using System;
using System.Collections.Generic;
using System.Threading;
class WebSocketBase
{
private WebSocket webSocketClient = null;
private WebSocketService webService = null;
private string url = null;
public WebSocketBase(string url, WebSocketService webService)
{
this.webService = webService;
this.url = url;
}
public void start()
{
webSocketClient = new WebSocket(url);
webSocketClient.OnError += new EventHandler<WebSocketSharp.ErrorEventArgs>(webSocketClient_Error);
webSocketClient.OnOpen += new EventHandler(webSocketClient_Opened);
webSocketClient.OnClose += new EventHandler<WebSocketSharp.CloseEventArgs>(webSocketClient_Closed);
webSocketClient.OnMessage += new EventHandler<MessageEventArgs>(webSocketClient_MessageReceived);
webSocketClient.ConnectAsync();
}
private void webSocketClient_MessageReceived(object sender, MessageEventArgs e)
{
webService.onReceive(e.Data);
}
public void send(string channel)
{
webSocketClient.Send(channel);
}
public void sendData(string data)
{
send("data");
}
}
interface WebSocketService
{
void onReceive(String msg);
}
Logic.cs
class Logic : WebSocketService
{
public void onReceive(string msg)
{
Console.WriteLine("Received message")
}
}
Maybe this was not your intent (comment and I will edit) but I the simplest thing would be to extend the base type AND implement your interface.
class Logic : WebSocketBase, WebSocketService
{
public void onReceive(string msg)
{
Console.WriteLine("Received message")
// Call method defined in base
sendData(msg);
}
}
As indicated by other comments, you're not doing anything with the WebSocketBase class.
A few other stylistic points:
a) WebSocketService should be "IWebSocketService" by convention
b) If WebSocketBase's sole purpose is to be a base class you should make it abstract
c) Be sure to mark your classes and interfaces themselves with access modifiers too (not just the methods inside them)
public interface IWebSocketService
{
void onReceive(String msg);
}
public abstract class WebSocketBase : IWebSocketService
{
...
private void webSocketClient_MessageReceived(object sender, MessageEventArgs e)
{
webService.onReceive(e.Data);
}
public void sendData(string data)
{
send("data");
}
}
public class Logic : WebSocketBase
{
public void onReceive(string msg)
{
Console.WriteLine("Received message")
}
}
So it looks like your WebSocketBase has a dependency on the service. Why not make the service know about what WebSocketBase is sending it messages?
interface WebSocketService
{
void onReceive(WebSocketBase sender, String msg);
}
class Logic : WebSocketService
{
public void onReceive(WebSocketBase sender, string msg)
{
sender.send("blah");
}
}
class WebSocketBase
{
...
private void webSocketClient_MessageReceived(object sender, MessageEventArgs e)
{
webService.onReceive(this, e.Data);
}
public void send(string channel)
{
webSocketClient.Send(channel);
}
...
}
Related
Lately I've stuck with some project. What I want to do?
I have some number of classes. Let's say something like that:
public class ActionEventArgs : EventArgs
{
public Creature actor;
}
public class LocationEventArgs : ActionEventArgs
{
public Location loc;
}
public class Action
{
public virtual void Do(object sender, ActionEventArgs e)
{
//... do something with it;
}
}
public class LocationAction : Action
{
public override void Do(object sender, LocationEventArgs e) // error, signatures differs
{
//... do something with it;
}
}
public class MainClass
{
public Action a { get; protected set; }
public void InitAction()
{
a = new LocationAction();
}
public void DoAction(Creature actor, Location location)
{
a.Do(this, new LocationEventArgs() { actor = actor, loc = location });
}
}
Well, it didn't work because of different methods signatures. Ok.
Of course, I can use something like class checks like:
public class LocationAction : Action
{
public override void Do(Action sender, ActionEventArgs e)
{
if (e is LocationEventArgs) throw new ArgumentException("e must be LocationEventArgs");
//... do something with it;
}
}
But I don't really like it, because it's only runtime thing. So, the question is: how to do this properly? Is there a way?
I think you want to use generics:
public class Action<TArg> where TArg : ActionEventArgs
{
public virtual void Do(object sender, TArg e)
{
// can access 'e.actor'
}
}
public class LocationAction : Action<LocationEventArgs>
{
public override void Do(object sender, LocationEventArgs e)
{
// can access 'e.actor' and 'e.loc'
}
}
I think what you are willing to do goes against the principle itself. You can't override and change the parameters. maybe add a
public override void Do(object sender, LocationEventArgs e) // error,
signatures differs
{
//... do something with it;
}
in your action class ?
I want to bubble up a message through classes. I used events and did this:
public class TopLevel{
public event EventHandler<string> Message;
public MiddleLevel mid;
public TopLevel()
{
mid.Message += (s, e) => { Message(s, e) };
}
}
public class MiddleLevel{
public event EventHandler<string> Message;
public BottomLevel bottom;
public MiddleLevel()
{
bottom.Message += (s, e) => { Message(s, e) };
}
}
public class BootomLevel{
public event EventHandler<string> Message;
public void DoSomething()
{
Message?.Invoke(this, "I did it.");
}
}
public class Handler{
public void HandleEvent(TopLevel top)
{
top.Message += PrintMessage;
}
public void PrintMessage(object sender, string message)
{
Console.WrteLine(message);
}
}
Also tried changing constructor to lambda expressions like this:
public class TopLevel{
public event EventHandler<string> Message;
public MiddleLevel mid;
public TopLevel()
{
mid.Message += (s, e) => { Message?.Invoke(s, e); };
}
}
public class MiddleLevel{
public event EventHandler<string> Message;
public BottomLevel bottom;
public MiddleLevel()
{
bottom.Message += (s, e) => { Message?.Invoke(s, e); };
}
}
public class BootomLevel{
public event EventHandler<string> Message;
public void DoSomething()
{
Message?.Invoke(this, "I did it.");
}
}
public class Handler{
public void HandleEvent(TopLevel top)
{
top.Message += PrintMessage;
}
public void PrintMessage(object sender, string message)
{
Console.WrteLine(message);
}
}
Codes above doesn't print any message. Even if I handle event in MiddleLevel class, I still get no message. I assume it is because message call is made in constructor (Even though linq quarries update themselves)? If I handle event in Handle class straight from BottomLevel class, it obviously - works. But I need to bubble the message up, I can't think of any other way to to this, because of how classes are constructed. Is it even possible to do what I have in mind with a standard Eventhandler class? If so than how? Should I just make an event class myself as in one of the sites i refered?
I refered to these sites:
What is the preferred way to bubble events?
https://www.carlosble.com/2016/04/event-bubbling-in-c/
Updated answer:
If you want 'Handler' to be triggered you will have to make sure that 'BottomLevel' falls within the hierarchy of the 'TopLevel' class being passed to the handler, this can be done via dependency injection (DI).
If 'BottomLevel' instantiates it's own classes (no DI) then it will not know about 'Handler', so handler will never be triggered.
If you comment out the DI setup and un-comment the 'BottomLevel' instantiation you can see the different behaviors.
class Program
{
static void Main(string[] args)
{
//setup the classes (dependency injection)
TopLevel topLevel = new TopLevel();
MiddleLevel middleLevel = new MiddleLevel(topLevel);
BottomLevel bottomLevel = new BottomLevel(middleLevel);
//set up the handler
Handler h = new Handler(topLevel);
//using this will not link to 'Handler' as there is no relation between this bottom and top
//BottomLevel bottomLevel = new BottomLevel();
//trigger the bottom class
bottomLevel.TriggerBottom();
//or
bottomLevel.DoSomething(null, "call from main");
Console.ReadLine();
}
}
public class Handler
{
TopLevel _topLevel;
public Handler(TopLevel topLevel)
{
if (topLevel != null)
_topLevel = topLevel;
_topLevel.Message += _topLevel_Message;
}
private void _topLevel_Message(object sender, string e)
{
Console.WriteLine($"handler triggered : {e}");
}
}
public class TopLevel
{
public event EventHandler<string> Message;
public TopLevel()
{ }
public void TriggerTop()
{
Message?.Invoke(this, "origin top");
}
public void DoSomething(object sender, string e)
{
Console.WriteLine($"Do something at top : {e}");
Message?.Invoke(this, e);
}
}
public class MiddleLevel
{
TopLevel _TopLevel;
public event EventHandler<string> Message;
public MiddleLevel(TopLevel topLevel) : this()
{
_TopLevel = topLevel;
}
public MiddleLevel()
{
if (_TopLevel == null)
_TopLevel = new TopLevel();
//subscribe this message to bottom message event method
Message += (s, e) => { _TopLevel.DoSomething(s, e); };
}
public void TriggerMiddle()
{
Message?.Invoke(this, "origin middle");
}
public void DoSomething(object sender, string e)
{
Console.WriteLine($"do something in middle : {e}");
//invoke the event(s)
Message?.Invoke(sender, e);
}
}
public class BottomLevel
{
MiddleLevel _MidLevel;
public event EventHandler<string> Message;
public BottomLevel(MiddleLevel midLevel) : this()
{
_MidLevel = midLevel;
}
public BottomLevel()
{
if (_MidLevel == null)
_MidLevel = new MiddleLevel();
////here you assign it
Message += (s, e) => { _MidLevel.DoSomething(s, e); };
}
public void TriggerBottom()
{
DoSomething(this, "origin bottom");
}
public void DoSomething(object sender, string e)
{
Console.WriteLine($"do something at bottom : {e}");
Message?.Invoke(sender, e);
}
}
I am trying to understand a piece of code in a legacy silverlight application.In this code as you can see user can publish an event and subscribe to that event.
while publishing event
Messenger.Publish<ErrorInformationData>(MessageConstant.ShowMessageTechnicalError,
new ErrorInformationData(ServiceOperationName.ClaimsService_GetClaim, ServiceOperationOccurence.DataServiceUI));
then subscribing to that event
Messenger.Subscribe<ErrorInformationData>(
this,
MessageConstant.ShowMessageTechnicalError,
(result) =>
{
Messenger.Publish(MessageConstant.ShowMessage,
new MessageData
{
Title = "Common$TechnicalError",
MessageText = "Common$TechnicalErrorDetail",
TextParameters = new object[] { result.OperationErrorCode.ToString() },
MessageType = MessageData.MessageTypes.OK,
OKAction = () =>
{
HtmlPage.Window.Navigate(new Uri("", UriKind.Relative));
},
MessageLevel = MessageData.MessageLevels.Error
}
);
}
);
Question is why do I need to use this framework where instead I can simply invoke a method.Also can anyone point to any documentation/tutorial regarding this communication.
Thanks #Nikosi for pointer, after more investigation I have found what's going on under the hood.
So there is a IMessanger interface which contains signature of publish,subscribe and unsubscribe method.
public interface IMessanger : IDisposable
{
void Subscribe(IReceiver receiver, int messageId);
void Publish<TEventArgs>(object sender, TEventArgs e, int messageId)
where TEventArgs : EventArgs;
void Unsubscribe(IReceiver receiver, int messageId);
}
Now we define a class Messanger which implements the interface.
public sealed class Messanger : IMessanger
{
private readonly Dictionary<int, List<IReceiver>> messageIdToReceiver;
public Messanger()
{
this.messageIdToReceiver = new Dictionary<int, List<IReceiver>>();
}
public void Subscribe(IReceiver receiver, int messageId)
{
List<IReceiver> receivers;
if (this.messageIdToReceiver.TryGetValue(messageId, out receivers))
{
receivers.Add(receiver);
}
else
{
this.messageIdToReceiver.Add(messageId, new List<IReceiver>() { receiver });
}
}
public void Publish<TEventArgs>(object sender, TEventArgs e, int messageId)
where TEventArgs : EventArgs
{
List<IReceiver> receivers;
if (this.messageIdToReceiver.TryGetValue(messageId, out receivers))
{
foreach (IReceiver receiver in receivers)
{
IReceiver<TEventArgs> receiverToReceive = receiver as IReceiver<TEventArgs>;
if (receiverToReceive != null)
{
receiverToReceive.Receive(sender, e, messageId);
}
}
}
}
public void Unsubscribe(IReceiver receiver, int messageId)
{
List<IReceiver> receivers;
if (this.messageIdToReceiver.TryGetValue(messageId, out receivers))
{
if (receivers.Count > 1)
{
receivers.Remove(receiver);
}
else if(receivers.Count == 1)
{
this.messageIdToReceiver.Remove(messageId);
}
}
}
public void Dispose()
{
this.messageIdToReceiver.Clear();
}
}
public interface IReceiver<TEventArgs> : IReceiver
where TEventArgs : EventArgs
{
void Receive(object sender, TEventArgs e, int messageId);
}
public interface IReceiver : IDisposable
{
}
Now we can see the usage of the above,Defined two classes one is publishing the event and other one is receiving the event.
public class PresenterA : IReceiver<EventArgs>, IDisposable
{
readonly IMessanger messanger;
public PresenterA(IMessanger messanger)
{
this.messanger = messanger;
this.messanger.Subscribe(this, (int)PubSubMsg.AppInstl);
}
public void Receive(object sender, EventArgs e, int messageId)
{
if ((PubSubMsg)messageId == PubSubMsg.AppInstl)
{
//Now that you received the message, update the UI, etc...
}
}
public void Dispose()
{
this.messanger.Unsubscribe(this, (int)PubSubMsg.AppInstl);
}
}
public class PresenterB
{
readonly IMessanger messanger;
public PresenterB(IMessanger messanger)
{
this.messanger = messanger;
}
public void btnApplicationRemove(object sender, EventArgs e)
{
//Do what you need to do and then publish the message
this.messanger.Publish<EventArgs>(this, e, (int)PubSubMsg.AppInstl);
}
}
public enum PubSubMsg
{
AppInstl = 1
}
I have a parent class that is firing an event to derived classes. The problem is that the event handler is alway null.
Class Plugin()
{
public delegate void BufferReadyHandler(string str);
public event BufferReadyHandler OnBufferReady;
public ClassPlugin(eGuiType _guyType)
{
GuiType = _guyType;
}
protected void Sp_DataReceived_Parent(object sender, SerialDataReceivedEventArgs e)
{
strCommonBuffer += serial.ReadExisting();
if (strCommonBuffer.Contains("\r\n"))
{
if (OnBufferReady != null) <<-------NULL
OnBufferReady(strCommonBuffer);
strCommonBuffer = string.Empty;
}
}
}
then there are some derived classes that are linked to that event:
class ClassIO : ClassPlugin
{
public ClassIO(eGuiType _guyType) : base(_guyType)
{
...
OnBufferReady += ClassIO_OnBufferReady;
}
private void ClassIO_OnBufferReady(string str)
{
...
}
}
the problem is that the OnBufferReady event in the parent class is alway null and therefore never fired.
Thanks for any help.
I might be wrong but have you thought about making the event static?
public delegate void BufferReadyHandler(string str);
public static event BufferReadyHandler OnBufferReady;
I am not sure why you are having this problem, I suspect it has something to do with the code you have not shown us. However in this situation I would not have the child subscribe to the event at all, instead make a protected method that raises the event that the child can override.
Here is how I would implement the class.
public class BufferReadyEventArgs : EventArgs
{
public BufferReadyEventArgs(string commonBuffer)
{
CommonBuffer = commonBuffer;
}
public string CommonBuffer {get; private set;}
}
Class Plugin()
{
public event EventHandler<BufferReadyEventArgs> OnBufferReady;
public ClassPlugin(eGuiType _guyType)
{
GuiType = _guyType;
}
protected void Sp_DataReceived_Parent(object sender, SerialDataReceivedEventArgs e)
{
strCommonBuffer += serial.ReadExisting();
if (strCommonBuffer.Contains("\r\n"))
{
RaiseOnBufferReady(strCommonBuffer);
strCommonBuffer = string.Empty;
}
}
protected virtual void RaiseOnBufferReady(string commonBuffer)
{
var temp = OnBufferReady;
if(temp != null)
temp(this, new BufferReadyEventArgs(commonBuffer));
}
}
class ClassIO : ClassPlugin
{
public ClassIO(eGuiType _guyType) : base(_guyType)
{
...
}
protected override void RaiseOnBufferReady(string commonBuffer)
{
base.RaiseOnBufferReady(commonBuffer);
...
}
}
Here is a working example based on your code:
using System;
using System.Collections.Generic;
public class MyClass
{
public static void Main()
{
ClassIO c = new ClassIO();
c.DataReceived();
Console.ReadLine();
}
}
public class ClassPlugin
{
public delegate void BufferReadyHandler(string str);
public event BufferReadyHandler OnBufferReady;
public ClassPlugin()
{
}
public void DataReceived()
{
if (OnBufferReady != null) {
OnBufferReady("Calling OnBufferReady");
}
}
}
public class ClassIO : ClassPlugin
{
public ClassIO() : base()
{
OnBufferReady += ClassIO_OnBufferReady;
}
private void ClassIO_OnBufferReady(string str)
{
Console.WriteLine("Inside ClassIO_OnBufferReady");
}
}
I don't understand why you would like to work with events in the first place for communication between parent and derived class.
If you need this communication, you would be better of with an (abstract) method in your base class that you implement in your derived classes.
If you need communication to all instances of derived types, you should look into composition instead of inheritance. Make some sort of manager instance that holds references to a list of instances of that base type and invokes a certain method on each of them in case of an 'event'.
We have an exercise about inheritance in c#. Now my problem is that what will i put in the question mark and in the if statement to know that the program passed a Person class or an Animal class or any class under InventoryApplication namespace. :)
private void AddButton_Click(object sender, EventArgs e)
{
Logic_Layer.Logic logic = new Logic();
//logic.Add<Person>();
}
namespace Logic_Layer
{
public class Logic
{
public void Add<InventoryApplication>() where InventoryApplication : ?
{
//if { }
}
public void delete() { }
public void edit() { }
public void search() { }
public void searchAll() { }
}
}
You can't use such a statement in the constraint. However, later in the method you can do this:
if (typeof(myObject).Namespace == "InventoryApplication")
{
...
}
What would be better is if the classes you want to test for (Animal, Person etc.) would implement an interface (say, IMyInterface).
For example:
void Add<T>(<T> param) where T : IMyInterface {/*...*/}