I am trying to subscribe to an event inside Singleton class.
public class Singleton : IDisposable
{
private static readonly Singleton _instance = new Singleton();
public static Singleton Instance => _instance;
static Singleton()
{
AppSettings.Instance.OnUpdated += OnAppSettingsUpdated;
OnAppSettingsUpdated(null, null);
}
public void Dispose()
{
AppSettings.Instance.OnUpdated -= OnAppSettingsUpdated;
}
private static void OnAppSettingsUpdated(object sender, EventArgs e)
{
// do something
}
}
AppSettings is another singleton class.
public partial class AppSettings
{
public EventHandler OnUpdated;
}
When OnUpdated invoked, nothing happens. It looks like OnAppSettingsUpdated is not subscribed.
In a code I use Singleton like this.
Singleton instance = Singleton.Instance;
Maybe I missed something?
It is important to subscribe inside Singleton class.
I suspect that the issue is that you have never accessed the Instance property of your Singleton class. Until you actually use the class, none of the code within it will be executed, including static members. In order for your static field to be assigned and your static constructor to be run, you need to actually use the class somehow. Try assigning its Instance property to a variable somewhere and I think you'll find that your event handler will be executed when you expect it to be.
EDIT:
When I run this code, I see nothing in the console:
class Program
{
static void Main(string[] args)
{
Singleton2.Instance.RaiseSomethingHappened();
}
}
public class Singleton1
{
private static Singleton1 _instance = new Singleton1();
public static Singleton1 Instance => _instance;
private static void Singleton2_SomethingHappened(object sender, EventArgs e)
{
Console.WriteLine("Singleton2_SomethingHappened");
}
public Singleton1()
{
Singleton2.Instance.SomethingHappened += Singleton2_SomethingHappened;
}
}
public class Singleton2
{
private static Singleton2 _instance = new Singleton2();
public static Singleton2 Instance => _instance;
public event EventHandler SomethingHappened;
protected virtual void OnSomethingHappened()
{
SomethingHappened?.Invoke(this, EventArgs.Empty);
}
public void RaiseSomethingHappened()
{
OnSomethingHappened();
}
}
When I change this:
static void Main(string[] args)
{
Singleton2.Instance.RaiseSomethingHappened();
}
to this:
static void Main(string[] args)
{
var s1 = Singleton1.Instance;
Singleton2.Instance.RaiseSomethingHappened();
}
and run the code again, I see the expected output in the console window. Either you're not actually using the single instance of the class handling the event or you're not registering the event handler correctly. This code demonstrates that the former makes a difference and how to do the latter.
Related
today I face an issue with some code I have written and really don't know where I have gone wrong, I'll keep it short and sweet basically the GetServer() method in the Faze class is returning null and I am really not sure why, but I was hoping you guys could help me with that.
I have left a few code snippets below of each class involved in the issue and where its initially called to give you a better idea on where things are going wrong.
Program.cs entry point..
static void Main(string[] args)
{
XmlConfigurator.Configure();
Faze.run();
while (true)
Console.ReadKey();
}
Faze class
public static class Faze
{
private static FazeServer fazeServer;
public static void run()
{
Console.Title = "Loading...";
fazeServer = new FazeServer("");
}
public static FazeServer GetServer()
{
return fazeServer;
}
}
FazeServer class
public sealed class FazeServer
{
private ConsoleWorker consoleWorker;
public FazeServer(string lol)
{
LoadServer();
}
private void LoadServer()
{
consoleWorker = new ConsoleWorker();
classLogger.Info("Server has been loaded.");
}
}
ConsoleWorker class
class ConsoleWorker : IDisposable
{
private readonly Timer consoleWorkerTimer;
private readonly int consoleWorkerInterval;
private static ILog classLogger;
public ConsoleWorker()
{
if (Faze.GetServer() == null)
throw new Exception("Server null..");
consoleWorkerInterval = int.Parse(Faze.GetServer().GetConfig().GetConfigElement("console.worker.interval"));
consoleWorkerTimer = new Timer(TimerElapsed, null, TimeSpan.FromMilliseconds(consoleWorkerInterval), TimeSpan.FromMilliseconds(consoleWorkerInterval));
classLogger = LogManager.GetLogger(typeof(ConsoleWorker));
}
private void TimerElapsed(object timerObject)
{
// Do something...
}
public void Dispose()
{
consoleWorkerTimer.Dispose();
}
}
After following the trace, the code that interrupts it is my null check
if (Faze.GetServer() == null)
throw new Exception("Server null..");
Before I added the if statement the line that caused an exception was
consoleWorkerInterval = int.Parse(Faze.GetServer().GetConfig().GetConfigElement("console.worker.interval"));
Why is GetServer() returning null, can anyone help?
I am after a few beers but in the class 'Faze' you have implemented a static field: 'fazeServer' and did not assign a value to it - therefore it is null.
If you would like to assign a value to 'fazeServer' static field please implement in example a static constructor for the class 'Faze' - in example: '
static Faze() { fazeServer = new FazeServer("whatEverString");}'
and that should solve the NRE.
Regards,
P.Sz.
Class fields are initialized to null by default so your code is the equivalent of:
public static class Faze
{
private static FazeServer fazeServer = null;
public static FazeServer GetServer() => fazeServer;
}
of course, calling GetServer() will return the unchaged value which is null.
If you want to initialize it yourself, use a static constructor:
public static class Faze
{
private static FazeServer fazeServer;
static Faze()
{
fazeServer = new FazeServer("");
}
}
or the field initializer:
public static class Faze
{
private static FazeServer fazeServer = new FazeServer("");
}
So it will be certain that you will get an instance when you call GetServer().
You're calling GetServer() before a value has been set in the fazeServer static variable.
The call stack is as follows:
fazeServer = new FazeServer("");
- LoadServer();
- - consoleWorker = new ConsoleWorker();
- - - if (Faze.GetServer() == null)
Or, in plain English:
fazeServer is set to the return value of new FazeServer()
new FazeServer() internally calls LoadServer()
LoadServer() internally calls new ConsoleWorker()
new ConsoleWorker() internally calls Faze.GetServer()
Faze.GetServer() returns the current value of fazeServer
So the code which sets that static variable is internally trying to read that static variable before it has finished setting it.
Apologies had a typo...have edited...
I have a weird issue I am not sure about.
In one piece of code I have a class which is called as a singleton which has an event other classes can listen to, pretty straightforward by doing something like
Client.Instance.MyEvent += new EventHandler<EventArgs>(myHandler);
So if I have a generic class:
Class MyTest {
public MyTest() {
System.Console.WriteLine("In Constructor Registering Events");
Client.Instance.MyEvent += new EventHandler<EventArgs>(myHandler);
}
private void myHandler(object sender, EventArgs arg) {
System.Console.WriteLine("Got event!");
}
}
Now if i create the class like:
MyTest mC = new MyTest ();
Client.Instance.FireEvent();
I get the expected "In Constructor Registering Events" and "Got Event"
However if i create the class through Reflection, I do not.
Type mType = typeof(MyTest);
object mT = Activator.CreateInstance(mType);
Client.Instance.FireEvent();
All i get is "In Constructor Registering Events" but i DO NOT get the event fired message. whats going on here? Am i doing something incorrectly in my reflection calls?
Thanks -
I've just tested your claim and, with the proper type, it works the same whether the object is created using new or via reflection.
The following Working Demo can be tested here
public class Program
{
public static void Main(string[] args)
{
Client.Instance.MyEvent += delegate { Console.WriteLine("MY EVENT handled from Main"); };
MyTest mt = new MyTest();
Type mType = typeof(MyTest);
object reflectedMT = Activator.CreateInstance(mType);
Client.Instance.FireEvent();
}
}
public class Client {
private Client() {}
private static Client _inst = new Client();
public static Client Instance { get { return _inst; } }
public void FireEvent() { if(MyEvent != null) MyEvent(this, EventArgs.Empty); }
public event EventHandler<EventArgs> MyEvent;
}
public class MyTest {
public MyTest() {
System.Console.WriteLine("In Constructor Registering Events");
Client.Instance.MyEvent += new EventHandler<EventArgs>(myHandler);
}
private void myHandler(object sender, EventArgs arg) {
System.Console.WriteLine("Got event!");
}
}
I have a Windows Mobile 6.5 (.net cf 3.5) that uses a singleton class which follows this pattern:
public sealed class Singleton
{
static readonly Singleton instance=new Singleton();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}
Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
reference
My class used to collect GPS data from the Intermediate drive. What I want is to create an event on the singleton class that I can subscribe to? E.g. MyClass.Instance.LocationChanged += ...;
Any help would be greatly appreciated.
Mark
What's the problem?
public sealed class Singleton
{
... your code ...
public delegate LocationChangedEventHandler(object sender, LocationChangedEventArgs ea);
public event LocationChangedEventHandler LocationChanged;
private void OnLocationChanged(/* args */)
{
if (LocationChanged != null)
LocationChanged(this, new LocationChangedEventArgs(/* args */);
}
}
public class LocationChangedEventArgs : EventArgs
{
// TODO: implement
}
Call OnLocationChanged whenever you want to fire the event.
You should just be able to do this as you would an event on any class.
public event Action<object, EventArgs> LocationChanged;
you can then have a protected virtual method such as:
protected virtual void OnLocationChanged(EventArgs args)
{
if(LocationChanged != null)
{
LocationChanged(this, args);
}
}
You can fire off your OnLocationChanged method where ever you need too and the event's you've attached will do their thing.
Here is an example of what I would do in Visual Basic:
Public Class Class1
Public Shared WithEvents Something As New EventClass
Public Shared Sub DoStuff() Handles Something.Test
End Sub
End Class
Public Class EventClass
Public Event Test()
End Class
How do I do this in C#?
I know there is not a Handles clause in C# so I need some function that is called and assign the event handlers there. However, since it's a shared class, there is no constructor; I must put it somewhere outside of a function.
How can it be achieved?
You can use the static constructor...
static readonly EventClass _something;
static Class1()
{
_something = new EventClass();
_something.Test += DoStuff;
}
static void DoStuff()
{
}
Try the following
public static class Class1 {
private static EventClass something;
public static EventClass Something {
get { return something; }
}
static Class1 {
something = new Class1();
something.Test += DoStuff;
}
public static void DoStuff() {
...
}
}
This is how I understand I can implement the singleton pattern in C#:
public class ChesneyHawkes{
private static ChesneyHawkes _instance = new ChesneyHawkes();
public ChesneyHawkes Instance {get{return _instance;}}
private ChesneyHawkes()
{
}
}
What if I want to provide a single instance of an object, so that there can only ever be one, make the access to it public, but only allow it to be created or replaced by another singleton.
// The PuppetMaster should be the only class that
// can create the only existing Puppet instance.
public class PuppetMaster{
private static PuppetMaster_instance = new PuppetMaster();
public static PuppetMaster Instance {get{return _instance;}}
// Like a singleton but can be replaced at the whim of PuppetMaster.Instance
public static Puppet PuppetInstance {get {return Puppet;}}
private PuppetMaster()
{
}
public class Puppet{
// Please excuse the pseudo-access-modifier
puppetmasteronly Puppet(){
}
}
}
// To be accessed like so.
PuppetMaster.Puppet puppet = PuppetMaster.Instance.PuppetInstance;
You don't really need more than one singleton for that. Look at this example:
using System;
// interface for the "inner singleton"
interface IPuppet {
void DoSomething();
}
class MasterOfPuppets {
// private class: only MasterOfPuppets can create
private class PuppetImpl : IPuppet {
public void DoSomething() {
}
}
static MasterOfPuppets _instance = new MasterOfPuppets();
public static MasterOfPuppets Instance {
get { return _instance; }
}
// private set accessor: only MasterOfPuppets can replace instance
public IPuppet Puppet {
get;
private set;
}
}
class Program {
public static void Main(params string[] args) {
// access singleton and then inner instance
MasterOfPuppets.Instance.Puppet.DoSomething();
}
}