Basically I'm trying to build something similar to transaction scope but to track changes in objects.
I have an abstract RecordableObject class roughly looking as follows:
public abstract class RecordableObject : INotifyPropertyChanged
{
protected virtual void RaisePropertyChanged(string prop)
{
// remember previous values if recording is on
var e = PropertyChanged;
if (e != null)
{
e(this, new PropertyChangedEventArgs(prop));
}
}
public void UndoChanges()
{
}
public void StartRecording()
{
}
public void SuspendRecording()
{
}
public void StopRecording()
{
}
public event PropertyChangedEventHandler PropertyChanged;
}
And a recorder whom I want to manage all things:
public class ThreadStaticRecorder : IDisposable, IChangesRecorder
{
[ThreadStatic]
private static List<RecordableObject> recordingList;
public void Record(RecordableObject recordableObject)
{
if (recordingList == null)
{
recordingList = new List<RecordableObject>();
}
recordingList.Add(recordableObject);
}
public void Forget(RecordableObject recordableObject)
{
if (recordingList == null)
{
return;
}
recordingList.Remove(recordableObject);
}
public void Undo()
{
}
public void Dispose()
{
recordingList = null;
}
}
Now, the point is I don't know how to tie recorder and recordable objects together, and I don't want recordable objects to know anything about recorder.
Ideally, I'd like to be able to use it as follows:
public void TestRecorder(MyClass recorableObj)
{
recorableObj.Foo = 1;
using (var recorder = new ThreadStaticRecorder())
{
recorableObj.Foo = 2;
recorder.Undo();
}
Console.WriteLine(recorableObj.Foo); // 1
}
The reason TransactionScope works is that the objects affected by it all participate in the transaction system. So in some sense they do "know about" the TransactionScope class.
What you have there is a cool idea, but I don't think there's anything in the "stock" .NET framework that would allow you to accomplish what you are attempting here without your recordable objects being aware of the recorder in some way.
Related
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'.
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 believe I have a design question and I hope to get your input. I made a small program to illustrate my question. Basically, my program consists of a radio system that gets heard on every room in the building. The sound is conditional on the receiving end, depending if the room registers itself to the radio system.
My problem is that the message sent is triggered on every room, even if the room is not registered. I would prefer to do the condition before the message gets sent out, rather then on the receiving end. By doing this, I could save myself unnecessary traffic. Can anyone give me an idea or the correct way to resolve this type of situation?
Just for the record, I would prefer not to have multiple event handlers in the radio, since I don't know how many rooms there will be.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Radio
{
#region Speakers
public interface ISound
{
string sound { get; set; }
}
public abstract class RoomSpeaker : ISound
{
public string sound { get; set; }
}
public class Room1Speaker : RoomSpeaker
{
}
public class Room2Speaker : RoomSpeaker
{
}
public class BuildingSpeaker : RoomSpeaker
{
}
#endregion
#region Rooms
public abstract class Room
{
public Radio radioPlayer;
public string name;
public HashSet<Type> registeredSpeakers = new HashSet<Type>();
public virtual void RoomPlayer(string lyrics)
{
registeredSpeakers.Add(typeof(BuildingSpeaker));
Console.WriteLine(lyrics);
}
}
public class Room1 : Room
{
public Room1(Radio radioPlayer)
{
this.radioPlayer = radioPlayer;
name = "Room1";
registeredSpeakers.Add(typeof(Room1Speaker));
radioPlayer.onRadio += radioPlayer_onRadio;
}
// This is what I don't think I like. It will only do something if it's registered. That's fine.
// But on any radio message out, this room will get called regardless. Should I NOT be doing this? Should I go back to
// making an eventHandler for every room? rather then having one even handler for all the rooms and have a condition on the receiving end.
void radioPlayer_onRadio(object sender, ISound e)
{
if (registeredSpeakers.Contains(e.GetType()))
RoomPlayer(name + e.sound);
}
}
public class Room2 : Room
{
public Room2(Radio radioPlayer)
{
this.radioPlayer = radioPlayer;
name = "Room2";
registeredSpeakers.Add(typeof(Room2Speaker));
radioPlayer.onRadio += radioPlayer_onRadio;
}
void radioPlayer_onRadio(object sender, ISound e)
{
// same problem as in Room1.
if (registeredSpeakers.Contains(e.GetType()))
RoomPlayer(name + e.sound);
}
}
#endregion
public class Radio
{
public event EventHandler<ISound> onRadio;
public void PlayRoom1()
{
onRadio(this, new Room1Speaker() { sound = "Test" });
}
public void PlayRoom2()
{
onRadio(this, new Room2Speaker() { sound = "Test" });
}
public void PlayAllRooms()
{
onRadio(this, new BuildingSpeaker() { sound = "Test All Rooms" });
}
}
class Program
{
static void Main(string[] args)
{
var radio = new Radio();
var room1 = new Room1(radio);
var room2 = new Room2(radio);
radio.PlayRoom1();
radio.PlayRoom2();
radio.PlayAllRooms();
Console.ReadLine();
}
}
}
Okay, what you're looking at is the publish-subscribe pattern (AKA eventbus). In eventbus pattern, you have a class that registers listeners and sends messages. Listeners tell the event bus "I'm listening for an event X". When the eventbus "sends" event X it consults its list of listeners for that event and if they are registered, executes the method that the listener told it to execute.
public class EventBus
{
private Dictionary<Type, List<Action<IEvent>>> actions = new Dictionary<Type, List<Action<IEvent>>>();
public void Listen<T>(Action<IEvent> callback) where T : IEvent
{
if (!actions.ContainsKey(typeof(T)))
{
actions.Add(typeof(T), new List<Action<IEvent>>());
}
actions[typeof(T)].Add(callback);
}
public void ClearCallbacks<T>() where T : IEvent
{
actions[typeof (T)] = null;
}
public void Send<T>(T #event) where T : IEvent
{
if (!actions.ContainsKey(typeof(T)))
{
return;
}
foreach (var action in actions[typeof(T)])
{
action(#event);
}
}
}
public interface IEvent
{
}
Usage:
public static void main () {
var eventBus = new EventBus();
var aRoom = new NoisyRoom(eventBus);
var bRoom = new NoisyRoom(eventBus);
var cRoom = new NoisyRoom(eventBus);
var dRoom = new QuietRoom(eventBus);
eventBus.Send(new NoisyEvent()); //sends to a,b,c room
}
public class EasyListeningEvent : IEvent
{
}
public class QuietRoom
{
public QuietRoom(EventBus eventBus)
{
eventBus.Listen<EasyListeningEvent>(BringTheNaps);
}
private void BringTheNaps(IEvent #event)
{
//its been brought!
}
}
class NoisyEvent : IEvent
{
}
public class NoisyRoom
{
public NoisyRoom(EventBus eventBus)
{
eventBus.Listen<NoisyEvent>(BringTheNoise);
}
private void BringTheNoise(IEvent #event)
{
//its been brought!
}
}
Try something a little more like this:
Edit: Note that this is just a start in the right direction. You can take this a lot further. Basically what you have is a sound source and a sound emitter. Obviously a radio is a sound source, and a speaker is a sound emitter, but something like a room could be both. A radio should not know what a speaker or a room is, it should only know about emitters, and it should only send sounds to them. Based on this, a room should have a collection of emitters (which would probably be speakers), and when a room gets a sound from a radio, it would simply relay that to whatever emitters it has registered. There would also be nothing stopping you from registering speaker directly to a radio. This code should help show how you might implement all of that.
public class Radio
{
private HashTable<string, EventHandler<ISound>> rooms = new ...;
public void RegisterRoom(string room, EventHandler<ISound> onSound)
{
rooms[room] = onSound;
}
public void UnregisterRoom(string room)
{
rooms.Remove(room);
}
public void PlayRoom(string room)
{
EventHandler<ISound> onSound;
if (rooms.TryGetValue(room, out onSound))
{
onSound(this, new BuildingSpeaker() { sound = "Test" });
}
}
public void PlayAllRooms()
{
if (rooms.Count == 0)
{
return;
}
var speaker = new BuildingSpeaker() { sound = "Test All Rooms" };
foreach (var room in rooms)
{
room.Value(this, speaker);
}
}
}
I am new in designing API class library in C#. I want to build a class library which will be used by many clients. The clients will be referencing this DLL.
My specific scenario: Say for example there is a domain model class available in the API. The clients will query the API and get the list of these domain model classes. Now, on the basic of some condition and data, the clients will evaluate the expressions defined in the domain model class.
Here, whenever this evaluation happens, I want to log the data and the result into the database.
What have I tried: One solution, here, is that the client call the logging method directly on the API class. However, I don't want the client to know what all is happening on the API side. There should be Separation of Concerns and Single responsibility.
Another solution tried is Define few properties in the domain model class and the client will set these properties when the expressions are evaluated. On the domain model class side, I have defined a static event which is fired when these properties are changed. The main API class will be listening to the changes in these properties and will be executing the required actions.
Question: Here, I wanted to know is there any another suggested methodology or best practice to achieve this ?
I will appreciate your time and guidance. Thank you.
Here, is the code that I have tried.
Domain class
public class DomainClass
{
private bool isTrue;
public List<Expression> Expressions { get; set; }
public bool IsTrue
{
get
{
return isTrue;
}
set
{
isTrue= value;
OnPropertyChanged("isTrue");
}
}
#region Events
public static event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
Expression class
public class Expression
{
public string FieldName { get; set; }
public string Operator { get; set; }
public string Value { get; set; }
}
API class
public class APIClass
{
public APIClass()
{
DomainClass.PropertyChanged += DomainClass_PropertyChanged;
}
void DomainClass_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
// Call required method.
}
public List<DomainClass> GetDomainClass()
{
// Methods returns list of domain classes
}
public void LogDetails (DomainClass dmClass)
{
// Perform the required logic.
}
}
Client Side
public void ProcessDomainClasses()
{
APIClass api = new APIClass()
List<DomainClass> myDomainClasses = api.GetDomainClass();
for (int dIndex = 0; dIndex < myDomainClasses.Count; dIndex++)
{
// Logic to evaluate the list of expressions in the domain class based on the data the client is having.
// So, the client will check the expression: fieldName [operator] value is true or not
myDomainClasses[dIndex].IsTrue = true;
}
}
Let me know in case you need any more information. I appreciate your time.
Static events looks crappy for me(atleast in this scenario). I'd do it with interface say ILogDetails (give proper name)
public interface ILogDetails
{
void LogDetails(DomainClass dmClass);
}
Implement in ApiClass or some other class.
public class APIClass : ILogDetails
{
public APIClass()
{
}
public List<DomainClass> GetDomainClass()
{
return new List<DomainClass>()
{
new DomainClass(this)//Pass ILogDetails implementation
...
};
}
public void LogDetails(DomainClass dmClass)
{
// Perform the required logic.
}
}
public class DomainClass
{
private bool isTrue;
private ILogDetails logDetails;
//Make constructor internal to prevent client knowing this
internal DomainClass(ILogDetails logDetails)
{
this.logDetails = logDetails;
}
public List<Expression> Expressions { get; set; }
public bool IsTrue
{
get
{
return isTrue;
}
set
{
isTrue = value;
logDetails.LogDetails(this);//Call the LogDetails method
}
}
}
All I am trying to do is implementing the observer pattern.
So, I came up with this solution:
We have a PoliceHeadQuarters whose primary job is to send notifications to all those who are subscribed to it. Consider that the DSP, Inspector and SubInspector classes are subscribed to PoliceHeadQuarters.
Using Events and Delegates I wrote
public class HeadQuarters
{
public delegate void NewDelegate(object sender, EventArgs e);
public event EventHandler NewEvent;
public void RaiseANotification()
{
var handler = this.NewEvent;
if (handler != null)
{
handler(this, new EventArgs());
}
}
}
public class SubInspector
{
public void Listen(object sender, EventArgs e)
{
MessageBox.Show(string.Format("Event Notification received by sender = {0} with eventArguments = {1}", sender, e.ToString()));
}
}
public class Inspector
{
public void Listen(object sender, EventArgs e)
{
MessageBox.Show(string.Format("Event Notification received by sender = {0} with eventArguments = {1}", sender, e.ToString()));
}
}
and this is how I invoked it
var headQuarters = new HeadQuarters();
var SubInspector = new SubInspector();
var Inspector = new Inspector();
headQuarters.NewEvent += Inspector.Listen;
headQuarters.NewEvent += SubInspector.Listen;
headQuarters.RaiseANotification();
so, both Inspector and SubInspector classes get notification whenever there the function RaiseANotification() is invoked.
It seems that the DotNet Framework 4, 4.5 supports a new way called IObserver and IObservable.
Can anyone give me a super simple example using IObservable and IObserver pattern for the above scenario? I googled only to find the available examples in the internet too bloated and difficult to understand.
My hinch: (probably i think it's wrong)
class DSP : IObserver //since it observes the headquarters ?
class PoliceHeadQuarters: IObservable // since here's where we send the notifications ?
Thanks in advance.
EDIT: Somebody also said that the MSDN documentation is also incorrect for IObservable #
IObservable vs Plain Events or Why Should I use IObservable?.
Here's a modification of MSDN example to fit your framework:
public struct Message
{
string text;
public Message(string newText)
{
this.text = newText;
}
public string Text
{
get
{
return this.text;
}
}
}
public class Headquarters : IObservable<Message>
{
public Headquarters()
{
observers = new List<IObserver<Message>>();
}
private List<IObserver<Message>> observers;
public IDisposable Subscribe(IObserver<Message> observer)
{
if (!observers.Contains(observer))
observers.Add(observer);
return new Unsubscriber(observers, observer);
}
private class Unsubscriber : IDisposable
{
private List<IObserver<Message>> _observers;
private IObserver<Message> _observer;
public Unsubscriber(List<IObserver<Message>> observers, IObserver<Message> observer)
{
this._observers = observers;
this._observer = observer;
}
public void Dispose()
{
if (_observer != null && _observers.Contains(_observer))
_observers.Remove(_observer);
}
}
public void SendMessage(Nullable<Message> loc)
{
foreach (var observer in observers)
{
if (!loc.HasValue)
observer.OnError(new MessageUnknownException());
else
observer.OnNext(loc.Value);
}
}
public void EndTransmission()
{
foreach (var observer in observers.ToArray())
if (observers.Contains(observer))
observer.OnCompleted();
observers.Clear();
}
}
public class MessageUnknownException : Exception
{
internal MessageUnknownException()
{
}
}
public class Inspector : IObserver<Message>
{
private IDisposable unsubscriber;
private string instName;
public Inspector(string name)
{
this.instName = name;
}
public string Name
{
get
{
return this.instName;
}
}
public virtual void Subscribe(IObservable<Message> provider)
{
if (provider != null)
unsubscriber = provider.Subscribe(this);
}
public virtual void OnCompleted()
{
Console.WriteLine("The headquarters has completed transmitting data to {0}.", this.Name);
this.Unsubscribe();
}
public virtual void OnError(Exception e)
{
Console.WriteLine("{0}: Cannot get message from headquarters.", this.Name);
}
public virtual void OnNext(Message value)
{
Console.WriteLine("{1}: Message I got from headquarters: {0}", value.Text, this.Name);
}
public virtual void Unsubscribe()
{
unsubscriber.Dispose();
}
}
public class Program
{
public static void Main(string[] args)
{
Inspector inspector1 = new Inspector("Greg Lestrade");
Inspector inspector2 = new Inspector("Sherlock Holmes");
Headquarters headquarters = new Headquarters();
inspector1.Subscribe(headquarters);
inspector2.Subscribe(headquarters);
headquarters.SendMessage(new Message("Catch Moriarty!"));
headquarters.EndTransmission();
Console.ReadKey();
}
}
Another suggestion - you probably want to consider leveraging the reactive extensions library for any code using IObservable. The nuget package is Rx-Main and the homepage for it is here: http://msdn.microsoft.com/en-us/data/gg577609.aspx
Update: ReactiveX has been translated to many platforms and languages and is now managed as an open source project. Here is the landing page.
This will save you a lot of boilerplate code. Here's a super simple example:
var hq = new Subject<string>();
var inspectorSubscription = hq.Subscribe(
m => Console.WriteLine("Inspector received: " + m));
var subInspectorSubscription = hq.Subscribe(
m => Console.WriteLine("Sub Inspector received: " + m));
hq.OnNext("Catch Moriarty!");
It will output:
Inspector received: Catch Moriarty!
Sub Inspector received: Catch Moriarty!
Reactive Extensions is a big subject, and a very powerful library - worth investigating. I recommend the hands-on lab from the link above.
You would probably want to embed those subscriptions within your Inspector, SubInspector immplementatinos to more closely reflect your code. But hopefully this gives you an insight into what you can do with Rx.