Ok guys I'm totally new to stackoverflow, let me know if I stuff something up.
I am making a class library for sockets and then using the class library to make a server. The issue I've run into is this:
In the class library I have a class called sockets that has event handlers (you know like connection made, closed so on) and in the server I'm making, I have a class named player which inherits from sockets.
The problem pretty much comes down to this.
I use the OnConnectionMade event handler to create my player, but because I cant do instanceOfInheritedClass = intanceOfBaseClass, even when I make use of use of the event handlers, the event handlers wont trigger because instanceOfInheritedClass isn't pointing to intanceOfBaseClass event, if I pass through the parameters.
void hostManager_OnConnectionMade(object source, ConnectionArgs e)
{
Player socket = new Player(e.GetSocket());
socket.OnDataRecivedPostConvert += Socket_OnDataRecivedPostConvertLogin;
}
public Player(DDSocket socket)
{
this.Host = socket.Host;
this.Socket = socket.Socket;
//this.OnConnectionClosed += socket.OnConnectionClosed;
//this.OnDataRecivedPostConvert += socket.OnDataRecivedPostConvert;
//this.OnDataRecivedPostConvertHost += socket.OnDataRecivedPostConvertHost;
}
One of the solutions I came up with was that instead of inheriting, I can just make it a intanceOfBaseClass parameter in the player class. But that will prevent me from making proper use of object source from my event handlers which will mean I'll need to use linq or something to find the player from the socket or something like that.
The other thing I thought about doing was somehow passing the event handlers over, which you can see I tried, but don't know how to do.
Now after hours of looking it up I'm stuck. Any help is greatly appreciated
and any answer that solves this issue is fine. I'm not picky with how its solved.
Despite that your Player class is inherited from DDSocket, but in this scenario, it acts as the wrapper class of DBSocket, so there is one hack to achieve that, I think you have to do some further steps:
class DDSocket
{
public event Action OnConnectionClosed;
public void Raise()
{
if (OnConnectionClosed != null)
{
OnConnectionClosed();
}
}
}
class Player :DDSocket
{
// make new event look as the same base class
public new event Action OnConnectionClosed;
public Player(DDSocket socket)
{
socket.OnConnectionClosed += Socket_OnConnectionClosed;
}
private void Socket_OnConnectionClosed()
{
if (OnConnectionClosed != null)
{
OnConnectionClosed();
}
}
}
// test those 2 classes
static void Main()
{
DDSocket d = new DDSocket();
Player pl = new Player(d);
pl.OnConnectionClosed += () => MessageBox.Show("test");
d.Raise();
}
Related
In my script attached to my controllers I want to be able to reference the child object that the controller is holding at the time, but I’m not sure how.
Any idea how to do this, would I need to tag the objects or something along those lines?
One way to do it, which is something I've done before at least, is to use System events.
You make two events in your controllers:
event EventHandler OnPickedUp;
event EventHandler OnLetGo;
If you manage to get something within range of picking it up, you fire off the event OnPickekUp
public class MyVRController
{
public event EventHandler OnPickedup;
public event EventHandler OnLetGo;
private bool HasObject = false;
...
private void SuccessfullyPickedUp(GameObject pickedUpGO)
{
if(OnPickedUp != null)
{
HasObject = true;
OnPickedUp(pickedUpGO, null);
}
}
...
private void OnLetGo()
{
if(OnLetGo != null)
{
HasObject = false;
OnLetGo(this, null);
}
}
...
}
Then whatever needs to care about the fact that you picked something up or you dropped something, can do this:
public class MyGameManager
{
public void Start()
{
// However you reference the controllers, do it here.
myRightVRController.OnPickedUp += SomeFunc1;
myRightVRcontroller.OnLetGo += SomeFunc2;
myLeftVRController.OnPickedUp += SomeFunc3;
myLeftVRController.OnLetGo += SomeFunc4;
// The rest of your initialization...
}
}
If you want you can specify what controller the event came from in the EventArgs that can be passed (currently passing null).
Hope this helps!
Unity share differents assets/script to use VR. I try to develop a simple experience to improve my knowledge of the differents Unity features but I'm in trouble with a call to an event.
In the script MenuButton.cs you can subscribe to an OnButtonSelected event but I don't know how :
MenuButton.cs
public class MenuButton : MonoBehaviour
{
public event Action<MenuButton> OnButtonSelected; // This event is triggered when the selection of the button has finished.
...
private IEnumerator ActivateButton()
{
// If anything is subscribed to the OnButtonSelected event, call it.
if (OnButtonSelected != null)
OnButtonSelected(this);
}
}
I try multiple unsuccess way to subscribe this event from another script like :
namespace VRStandardAssets.Menu
{
public class GetDiscover : MonoBehaviour
{
[SerializeField] private MenuButton m_MenuButton; // This controls when the selection is complete.
void OnEnable()
{
m_MenuButton.OnButtonSelected += Teleport;
}
void OnDisable()
{
m_MenuButton.OnButtonSelected -= Teleport;
}
void Teleport()
{
Debug.Log("Hello");
}
}
}
But I have the error : "error CS0123: A method or delegate VRStandardAssets.Menu.GetDiscover.Teleport()' parameters do not match delegateSystem.Action(VRStandardAssets.Menu.MenuButton)' parameters".
What does that mean ? I'm just looking for the simplest way to call the event...
I also try with the delegate method but it won't work too...
Maybe I don't understand well how function the event system Unity and some clear explanation would be welcome even if I already follow some tutorial :
https://unity3d.com/fr/learn/tutorials/topics/scripting/events-creating-simple-messaging-system
https://unity3d.com/fr/learn/tutorials/topics/scripting/events
What this error is saying is that when you subscribe to the "OnButtonSelected" event, the method you target (in your case, "Teleport") must accept a parameter of type VRStandardAssets.Menu.MenuButton.
This is how the event system tells your listener which button was selected.
So, you could use something like this:
void Teleport(VRStandardAssets.Menu.MenuButton buttonPressed)
{
// if you care which button, access buttonPressed parameter here..
Debug.Log("Hello");
}
(Note: for good programming practice though I would suggest naming this something other than "Teleport" - calling it something like "HandleMenuButton" or "MenuButtonPressed" keeps its intent clear; then inside that method you can call a separate "Teleport" function. In the future if you need to change the interaction, it will be easier to update the code if you maintain that level of separation.)
I'm currently implementing a SignalR application to send a message to several clients when an external library I've written fire an event.
I want to attach a unique handler to my event for every instance of my hub, so I could send the messages only once when it is fired; but as SignalR instanciate many hubs on every request, I end up with more than one event handler attached every time. So my question is: what can I do to attach only once on my event ?
Here is my code:
public class MyHub : Hub
{
private static ExternalClass staticObject = new ExternalClass();
public MyHub()
{
staticObject.MyEvent += staticObject_MyEvent;
}
private void staticObject_MyEvent(object sender, EventArgs e)
{
//Some irrelevant code which send messages to clients
}
}
I know my question is pretty the same than this one and a lot of others, but I never found a satisfying anwser for multi-threaded or multi-instance environment - which is definitly my case.
Here is the code replacing my old event declaration in my library :
private bool isEventAlreadyRegistered = false;
private static readonly object verrou = new object();
private System.EventHandler myEvent = delegate { };
public event System.EventHandler MyEvent
{
add
{
if(!isEventAlreadyRegistered)
{
lock(verrou)
{
//Double check as multiple add can be made simultaneously
if(!isEventAlreadyRegistered)
{
isEventAlreadyRegistered = true;
myEvent += value;
}
}
}
}
remove
{
myEvent -= value;
}
}
It works magnificently. My only doubt was about the performances with the lock; but as it is used only on the first call, it's negligible.
Of course, this solution only works when you have access to the source code of your event.
Hubs live in transient life. Meaning it will be created for each type of transaction (connected, on client message, dissconnected etc).
Never, ever have anything else then SignalR logic in the hub. Move your code somewhere else and invoke the client method when you want to upate. Or use a library that already have abstracted that for your. For example this library (I'm the author)
https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/wiki
Live demo:
http://malmgrens.org/signalR/
I have a UserControl on a Form,
when I MouseMove on that UserControl I want to do something in the Form.
How can I make the Form 'listen' for this event?
I am using Visual C#, .Net framework 3.5, winforms
I suppose you're referring to a use control or something like that.
You can add a public event, and trigger it inside your class when detecting the inner class event.
Then you have to subscribe to the published event in the second class.
This is a sample so that you see the sintax:
public class WithEvent
{
// this is the new published event
public EventHandler<EventArgs> NewMouseEvent;
// This handles the original mouse event of the inner class
public void OriginalEventhandler(object sender, EventArgs e)
{
// this raises the published event (if susbcribedby any handler)
if (NewMouseEvent != null)
{
NewMouseEvent(this, e);
}
}
}
public class Subscriber
{
public void Handler(object sender, EventArgs e)
{
// this is the second class handler
}
public void Subscribe()
{
WithEvent we = new WithEvent();
// This is how you subscribe the handler of the second class
we.NewMouseEvent += Handler;
}
}
If you are talking about Windows Forms (it's not clear from the question) you need to define
a new event in the class who recieves the mouse-event. After reciving it raises a new custom-event. Another class is subcribed to that (custom-event) a recieves notification.
For moe information (it's not something that can be presenteed in a couple of lines)
can have alook here:
How to propagate an Event up to the MainForm?
If you are talking about WPF, there are different concept of events: event routing. If your class is UI element present in UI tree of the component that recieves actually mouse-event, it will be propagated to your class too. So no need of more coding.
To expand a little on the answer from JotaBe, there are two scenarios that I could see you having:
a) class A calls a method in class B, and an exception happens. In this case, you don't need to do anything: exception will walk the stack, until it finds a catch statement. So, really, all you need to do is NOT catch an exception, or if you do need to catch it (for logging purposes and such), then rethrow it.
b) if you need to have a code triggered in some unrelated class, as a result of exception, then the best way is to use events. In your class declare:
public class ClassA
{
public static event EventHandler<Exception> OnException;
public void Notify(Exception ex)
{
if (OnException != null)
{
OnException(this, ex);
}
}
}
and then, in order to be notified, all you need is to
ClassA.OnException += (sender, exeption) =>
{
... some GetHashCode ..
};
... I guess JotaBe already added all necessary example code as I was typing
I am wondering if the following is bad use of the Observer pattern. I know the Subject is supposed to be the one and the listener the many. However, I could end up with more subjects in my application than listeners!
The Players
Form1: Self explanatory
DocumentCreator: Contains a Factory Method and a Strategy for picking a file from a list
Document: Contains information about the document file and a Template method for children
Proposed
IErrorProne: interface for the above players to implement an event, turning them into subjects
Reporting: listens for IErrorProne objects and handles logging/emailing
DocumentState: This is a bonus that Im a bit iffy on. I havent quite settled on a good flow outside of the template. Currently I have a state machine inside the Document class. I want to pull the state machine out of the Document class and into Form1, decoupling the two from each other.
public interface IErrorProne
{
public delegate void ErrorEventDelegate(
object sender,
ErrorEventArgs e
);
public event ErrorEventDelegate ReportError;
}
public abstract class Document : IDisposable, IErrorProne // My Template
{
public void Process()
{
//Error Occured
OnReportError(); // safely triggers error reporting
}
}
public class Reporting
{
static Reporting instance = new Reporting();
public void HandleError(object sender, ErrorEventArgs e);
}
public partial class Form1
{
private DocumentCreator docFactory
= new DocumentCreator(new RandomPicking());
private Document theDoc = null;
private Reporting reporting = Reporting.Instance;
private DocState state = new InitialState();
//DocState not in this example but demonstrates how it might work
public Form1()
{
docFactory.ReportError += reporting.HandleError;
theDoc.ReportError += reporting.HandleError;
docFactory.ReportError += state.HandleError;
theDoc.ReportError += state.HandleError;
}
void BackgroundWork(...)
{
using (theDoc = DocumentFactory.Instance.CreateDocument())
{
if (theDoc != null)
theDoc.Process();
}
}
}
I guess my question is it an Anti-Pattern if I have a Many to One, rather than a One to Many?
If you think of it as publish-subscribe, then it really doesn't matter. If you take the Domain Event style, you can have anything and any number of things publish any given domain event, and anything and any number of things subscribe to domain events.
Many->Many, many->one, one->many are all valid.