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.
Related
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.
I started to transform my push -> pull bridge to a much simpler construct with Reactive Extensions.
So now I have a class with a (private) event, and an Observable created from it.
class WithEvents {
public class MyEvent {}
private delegate void MyEventHandler(MyEvent e);
private event MyEventHandler EventRaised;
Public IObservable<MyEvent> TheEvents;
public void Foo() {
EventRaised(new MyEvent());
}
}
Thing is, this event seems like unneeded scaffolding here. So I was wondering: is there a way to construct a 'bare' Observable, that I can just 'push' events to?
class WithChannel {
public class MyEvent {}
public IObservable<MyEvent> EventRaised {get} = new Channel<MyEvent>();
public void Foo() {
((Channel)EventRaised).DoNext(new MyEvent());
}
}
Yes, there is a thing called Subject (in System.Reactive.Subjects namespace) which does exactly that:
class WithChannel {
public class MyEvent {
}
private readonly Subject<MyEvent> _event;
public WithChannel() {
_event = new Subject<MyEvent>();
}
public IObservable<MyEvent> EventRaised => _event;
public void Foo() {
_event.OnNext(new MyEvent());
}
}
Usage of subjects is generally not recommended, but for this specific task I think it's fine.
I need to add the following to several unrelated classes:
private MyClass myclass;
private EventHandler clicked;
public event EventHandler Clicked { ... }
private bool enabled;
public bool Enabled { ... }
private void HandleClicked(object sender, EventArgs e) { ... }
The problem is these classes are third-party and do not necessarily share the same immediate base class though they all eventually inherit from a class called View. Right now, I end up creating my own subclasses for each and copy-pasting the same code which leads to unnecessary duplication.
Any way to meaningfully refactor this?
One of the way is to use composition. Create class which will store all new events\properties\methods:
public class Properties
{
private MyClass myclass;
private EventHandler clicked;
public event EventHandler Clicked { ... }
private bool enabled;
public bool Enabled { ... }
private void HandleClicked(object sender, EventArgs e) { ... }
}
Then use Extension methods to expand required interface (i.e. classA)
public static class NewInterfaces
{
public static Properties Props(this classA)
{ /* lookup required properties, from some associative storage */ }
}
Usage will look like:
var inst = new classA();
inst.Prop.Enabled = !inst.Prop.Enabled;
Second way it still composition, but you will use wrapper for those:
public class Wrapper
{
private object _wrapped;
public Wrapper(classA obj)
{
_wrapped = obj;
}
public Wrapper(classB obj)
{
_wrapped = obj;
}
public int WrappedProperty
{
get
{
var instA = _wrapped as classA;
if (instA != null)
return instA.SomeProperty1;
var instB = _wrapped as classB;
if (instB != null)
return instB.SomeProperty2;
}
}
private MyClass myclass;
private EventHandler clicked;
public event EventHandler Clicked { ... }
private bool enabled;
public bool Enabled { ... }
private void HandleClicked(object sender, EventArgs e) { ... }
}
Second way allow you to create new hierarchy of wrapper which will contain elements without common base class.
Inheritance becomes problematic in time. I recommend using interfaces instead, you will have much more flexibility.
public interface INewInterfaces
{
event EventHandler Clicked;
bool Enabled { get; }
void HandleClicked(object sender, EventArgs e);
}
public class NewClassA : ClassA, INewInterfaces
{
//...
}
public class NewClassB : ClassB, INewInterfaces
{
//...
}
Edit 1:
If you are saying that ClassX's are very similar and you want to use the same HandleClicked implementation in all of these unrelated classes, you may use two other approaches.
1- Still inheritance
Create an interface and add all the common functions across the classes you want to use. This will put the ClassX's in the same family. And then create a class for general use.
public interface IExistingInterfaces
{
void SomeMethod();
}
public class NewClassA : ClassA, IExistingInterfaces
{
//Do nothing
}
public class NewClassB : ClassB, IExistingInterfaces
{
//Do nothing
}
public class MyClassForGeneralUse : IExistingInterfaces
{
private IExistingInterfaces _baseObject;
public MyClassForGeneralUse(IExistingInterfaces baseObject)
{
_baseObject = baseObject;
}
//Write proxy calls for IExistingInterfaces
public void SomeMethod()
{
_baseObject.SomeMethod();
}
//Add new methods here
public void HandleClicked(object sender, EventArgs e)
{
}
//...
//...
}
Not: The first part is Bridge Pattern and the second part is Decorator Pattern
2- Reflection
var propertyInfo = someObject.GetType().GetProperty("property name");
if (propertyInfo == null)
throw new Exception(string.Format("Property does not exist:{0}", condition.Property));
var propertyValue = propertyInfo.GetValue(someObject, null);
long longValue = (long)propertyValue;
//You can get methods in a smilar manner and execute with
result = methodInfo.Invoke(methodInfo, parametersArray);
But reflection may be overkill.
I want an abstract class that raises an event, this event will be raised by the concrete class.
What I want is when I use another class to listen to these events the signature of the delegate should have the concrete type not the abstract, I don't want to cast it.
For the moment I have come up with this solution. It works but I don't find it particularly clever especially because of the "STUPID, DOESN'T MAKE SENSE......" part.
Here is my solution :
public delegate void ClassAEventHandler<TClassA>(TClassA classA) where TClassA : ClassA;
//Abstract class that raise Event
public abstract class ClassA<TClassA> : where TClassA : ClassA
{
public event ClassAEventHandler<TClassA> onClassEventRaised;
private TClassA eventClassA;
public void registerEventClass(TClassA classA)
{
this.eventClassA = classA;
}
public void raiseClassEvent()
{
this.onClassEventRaised(this.eventClassA);
}
}
// Exemple of concrete type
public class ClassB : ClassA<ClassB> // <------ IT SEEMS DUMB
{
public void action()
{
//Do something then raise event
this.raiseClassEvent();
}
public void saySomething() {};
}
// Exemple of concrete type
public class ClassC : ClassA<ClassC> // <------ IT SEEMS DUMB
{
public void command()
{
//Do something then raise event
this.raiseClassEvent();
}
public void destroySomething() {};
}
//Class that listen to the event raised
public class MyEventListener
{
private ClassB classB;
private ClassC classC;
public MyEventListener()
{
this.classB = new ClassB();
this.classB.registerEventClass(this.classB); // <------ STUPID, DOESN'T MAKE SENSE......
this.classB.onClassEventRaised += classB_onClassEventRaised;
this.classC = new ClassC();
this.classC.registerEventClass(this.classC); // <------ STUPID, DOESN'T MAKE SENSE......
this.classC.onClassEventRaised += classC_onClassEventRaised;
}
public void classB_onClassEventRaised(ClassB classB)
{
classB.saySomething();
}
public void classC_onClassEventRaised(ClassC classC)
{
classC.destroySomething();
}
//What i don't want
/*
public void classB_onClassEventRaised(ClassA classA)
{
((classB)classA).saySomething();
}
*/
}
First of all, you're not following regular event design in .NET.
Instead of implementing your own delegate, use EventHandler<TArgs>, and create a derived class of EventArgs.
Your CustomEventArgs should have a T generic parameter:
public class CustomEventArgs<T> where T : A
{
private readonly T _instance;
public CustomEventArgs(T instance)
{
_instance = instance;
}
public T Instance { get { return _instance; } }
}
Also, don't implement a custom way of registering events. If you want to encapsulate how handlers are added to the event, you need to use event accessors.
Finally, you could implement your classes as follows:
public class A<T> where T : A
{
private event EventHandler<CustomEventArgs<T>> _someEvent;
// An event accessor acts like the event but it can't be used
// to raise the event itself. It's just an accessor like an special
// event-oriented property (get/set)
public event EventHandler<CustomEventArgs<T>> SomeEvent
{
add { _someEvent += value; }
remove { _someEvent -= value; }
}
protected virtual void RaiseSomeEvent(CustomEventArgs<T> args)
{
// If C# >= 6
_someEvent?.Invoke(this, args);
// Or in C# < 6
// if(_someEvent != null) _someEvent(this, args);
}
}
public class B : A<B>
{
public void DoStuff()
{
// It's just about raising the event accessing the whole
// protected method and give an instance of CustomEventArgs<B>
// passing current instance (i.e. this) to CustomEventArgs<T>
// constructor.
RaiseSomeEvent(new CustomEventArgs<B>(this));
}
}
Now, if you try to handle SomeEvent, you'll get the CustomEventArgs<B> typed as B instead of A:
B b = new B();
b.SomeEvent += (sender, args) =>
{
// args.Instance is B
B instance = args.Instance;
};
b.DoStuff(); // Raises SomeEvent internally
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!");
}
}