Design notification structure for API in C# - c#

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
}
}
}

Related

Setting property of a subtype class using reference abstract type

So I have abstract class
public abstract class Client
{
public abstract void Send();
public abstract void Get();
}
And now there are 2 classes that inherit from Client
public class ClientV2 : Client
{
public string Value1 {get;set;}
//implement Send and Get method()
}
public class ClientV3 : Client
{
public string Value2 {get;set;}
public string Value3 {get;set;}
//implement Send and Get method()
}
For simplicity, Program class is general GUI class. Now when someone will click on checkbox a new object will be instantiated but also new controls will show, for example text box for Value 2. What I need to do is set a Value2 when someone will type something but since I am using abstract type I can't access that value, what do you think will be the best solution here?
public class Program
{
private Client client;
public void Client2CheckboxChecked()
{
client = new Client2();
}
public void Client2CheckboxChecked()
{
client = new Client3();
}
public void Value2Changed(string newValue)
{
//Here I would need to set Value2 propertyu of a ClientV3 using client
}
public void SendData()
{
client.Send();
}
}
I can of course create a different type for client 2 and client 3 that is rather than
private Client client;
I would have
private ClientV3 clientV2;
private ClientV3 clientV3;
But in a future there could also be a possibility for clientV4 and I want to minimize the amount of changes I would need to change in my Program class.
you may create an abstract method SetValue that all the different clients must implement and where the actual logic is in. Then in your Program.Value2Changed just call that method:
public void Value2Changed(string newValue)
{
client.SetValue(newValue); // may be ClientV2 or ClientV3 or whatever
}
class Client
{
public abstract void SetValue(string newValue);
}
class ClientV2 : Client
{
public override void SetValue(string newValue) => this.Value2 = newValue;
}
class ClientV3 : Client
{
public override void SetValue(string newValue) => this.Value3 = newValue;
}
This delegates the task of setting the values from your Program to the Client.
Since the parents cannot know what is in the inherited classes you can solve this problem with Downcasting
public void Value2Changed(string newValue)
{
(ClientV3)client.Value2 = newValue;
}

How can I build class similar to TransactionScope

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.

How to subscribe to an event fired from any Instance/Object of type X

i'm currently working on a small game-engine and i'm kinda stuck on finding the right pattern.
First here are some code snippets to understand what i'm trying to achieve :
The Unit : the ability-caster/target ( throw the ability or receive it)
public class Unit
{
public string Name { get; set; } // Unit name
public List<BaseAbility> MyAbilities{get; set;} // abilities that an unit has.
}
The Ability :
public abstract class BaseAbility
{
public string Name {get; set;} // ability name
public Unit Caster { get; set; } // ability caster (owner)
public List<BaseEffect> EffectList {get; set;} // effects that an ability possess
// apply all effects that this ability has on the selected target
public virtual void DoAbility(Unit target)
{
foreach (BaseEffect eff in this.EffectList)
{
eff.CalculateEffect(target);
}
}
// here we gonna subscribe to some events
public abstract void initListeners();
}
The Effect :
public abstract class BaseEffect
{
public BaseAbility Owner { get; set; } // each effect belong to an ability
protected string Name { get; set; } // effect name
public EventDispatcher Event { get; set; } // the event to dispatched when this effect is called or used
//apply effect on target
public virtual void CalculateEffect(Unit target)
{
// Do Stuffs here like damage and poison etc etc
this.Event.DispatchMyEvent();
}
}
the Event Dispatcher :
public class EventDispatcher
{
private object mySender;
private EffectEventArgs myArgument;
public delegate void EventHandler(object sender, EffectEventArgs argument);
public event EventHandler OnMyEvent;
public EventDispatcher(object sender, EffectEventArgs argument)
{
this.mySender = sender;
this.myArgument = argument;
}
public void DispatchMyEvent()
{
if (OnMyEvent != null)
{
OnMyEvent(this.mySender, this.myArgument);
Debug.WriteLine("event has been raised");
}
}
}
The Effect Event Arguments :
public class EffectEventArgs : EventArgs
{
private Unit target; // target affected by effect
// not sure if we even need this EffectEventArgs ?!
public EffectEventArgs(Unit unit)
{
this.target = unit;
}
}
Now i'm gonna create 2 effects and 2 abilities and 2 units for the simulation :
Fire Effect :
public class FireEffect : BaseEffect
{
public FireEffect(BaseAbility effectOwner)
{
this.Owner = effectOwner;
this.Name = "Fire";
}
public override void CalculateEffect(Unit target)
{
// set the event here (to get the target as argument for the event)
this.Event = new EventDispatcher(this.Owner, new EffectEventArgs(target));
base.CalculateEffect(target);
}
}
Wind Effect : same as fire effect but with a different name and event and apply also a different Effect.
Fire Ball ability :
public class FireBall : BaseAbility
{
public FireBall(Unit caster)
{
this.Name = "FireBall";
this.Caster = caster;
this.EffectList = new List<BaseEffect>();
this.EffectList.Add(new FireEffect(this)); // fire ball ability has "FireEffect" as effect
}
public override void DoEffect(Unit target)
{
base.DoEffect(target);
}
}
Two Units , let´s say :
"Dragon" as Unit => has FireBall (ability) and gonna hit =>
"shaolin master of the wind " as Unit has a passiveAbility called "WindFury"
WindFury :
public class PassiveAbility : BaseAbility
{
public PassiveAbility(Unit caster)
{
this.Name = "WindFury";
this.Caster = caster;
this.EffectList = new List<BaseEffect>();
this.EffectList.Add(new WindEffect(this));
this.initListeners(); // subscribe to events (aka add listeners)
}
public override void DoEffect(Unit target)
{
base.DoEffect(target);
}
// THE MAIN PROBLEM :
public override void initListeners()
{
// here i need to subscribe to an event fired from any Instance/Object of type FireEffect so that the targeted Unit
// can react to the Unit caster (kind of counter attack)
// to resume this , it should follows this logic :
// if any Ability has The effect(FireEffect => FireBall for example) was casted
// on this Unit thats possess this passive, react to it and counter with (WindEffect)
// otherwise put : when our dragon or Ryu or even Sasuke throw an ability with
// a FireEffect on our friend "Shaolin" ,he should react to it
// and send the attacker flying with a powerfull WindEffect
}
public void CallBack(object sender, EffectEventArgs e)
{
BaseAbility ab = (BaseAbility)sender;
this.DoEffect(ab.UnitCaster); // hit the unit caster back (revenge)
}
}
Notice please that we can have so many dragons and Shaolins in this game or simulation and any passive holder (unit) should only react to the attacker (unit) etc.
Edit : (Recap of the main problem)
How to subscribe via PassiveAbility.initListeners() to an event fired from any instance of type FireEffect (an ability that use fireEffect) ???
Many thanks in advance for your support and contribution.
Youness
Add a static EventDispatcher to FireEffect and subscribe to that.
public class FireEffect : BaseEffect
{
public static EventDispatcher FireEffectEventDispatcher = new EventDispatcher(null,null);
public FireEffect(BaseAbility effectOwner)
{
this.Owner = effectOwner;
this.Name = "Fire";
}
public override void CalculateEffect(Unit target)
{
// set the event here (to get the target as argument for the event)
FireEffectEventDispatcher.mySender = Owner;
FireEffectEventDispatcher.myArgument = new EffectEventArgs(target);
// Fire the event
FireEffectEventDispatcher.DispatchMyEvent();
//If you still want the base effect firing.
base.CalculateEffect(target);
}
}
To make this work, you'll also need to change your EventDispatcher to let you set the sender / argument after construction (not being able to doesn't make any sense anyway - it's a useless restriction).
I would recommend redoing (or removing) your EventDispatcher implementation, however. It makes no sense to set your event parameters in the constructor when they can more reasonably be set during event triggering.

Instantiating a delegate method to be used in a class library

I'm building an email-monitoring framework that I'll be using for a handful of users, so I'm building a class library to wrap everything in. I'm instantiating the configuration (sender, subject, last-received, ...) in a static class. Therefore, I have something like this.
public static class MyConfig
{
public static int Sender { get; set; }
// and so on and so forth
public static void BuildMyConfig(string theSender, string theRecipient, ...)
{
Sender = theSender;
// yada yada yada...
}
}
public class Monitoring
{
public delegate void DoSomethingWithEmail(EmailContents theContents);
public void StartMonitoring() {
//When I get an email, I call the method
DoSomethingWithEmail(theEmailWeJustGot);
}
}
Obviously, what we do with the email will be something completely different in each case. What I'm trying to is instantiate that delegate. Where would I do that? The MyConfig class and then invoke it from there as a static method? The instance of the Monitoring class?
An application would look like...
public class SpecificMonitor
{
Monitoring.BuildMyConfig("foo#bar.com", "bar#foo.com", ...);
Monitoring m = new Monitoring();
m.StartMonitoring();
//But where do I build the delegate method???
}
I've gotten compiling errors with every option I've tried so far. I've also tried overriding a method instead of using a delegate, using interfaces... but I think delegation is where it's at.
Thanks in advance!
Consistent with the rest of your design (although I do not necessarily agree that the design is great) you could allow for the callback to be set in the configuration class
public static class MyConfig
{
public static string Sender { get; set; }
public static DoSomethingWithEmail EmailReceivedCallback { get; set; }
public static void BuildMyConfig(string theSender, string theRecipient,
DoSomethingWithEmail callback)
{
Sender = theSender;
EmailReceivedCallback = callback;
}
}
// Make sure you bring the delegate outside of the Monitoring class!
public delegate void DoSomethingWithEmail(string theContents);
When an incoming email is acknowledged by your application you can now pass the email to the callback assigned to the configuration class
public class Monitoring
{
public void StartMonitoring()
{
const string receivedEmail = "New Answer on your SO Question!";
//Invoke the callback assigned to the config class
MyConfig.EmailReceivedCallback(receivedEmail);
}
}
Here is an example of usage
static void Main()
{
MyConfig.BuildMyConfig("...", "...", HandleEmail);
var monitoring = new Monitoring();
monitoring.StartMonitoring();
}
static void HandleEmail(string thecontents)
{
// Sample implementation
Console.WriteLine("Received Email: {0}",thecontents);
}
Define the constructor so that when people instantiate a Monitoring object, they must define the delegate:
public class Monitoring
{
public delegate void DoSomethingWithEmail(EmailContents theContents);
public Monitoring(Delegate DoSomethingWithEmail)
{
this.DoSomethingWithEmail = DoSomethingWithEmail;
}
public void StartMonitoring() {
//When I get an email, I call the method
DoSomethingWithEmail(theEmailWeJustGot);
}
}
Then pass in the delegate you want when you instantiate each Monitoring:
Monitoring m = new Monitoring(delegate(EmailContents theContents)
{
/* Do stuff with theContents here */
});
m.StartMonitoring();

Communication between ViewModels via events

I have an application where I open a new view (with viewmodel) within another viewmodel. The new Viewmodel needs some parameters from the caller viewmodel.
Now I introduced a class called Messenger which looks like:
public class Messenger
{
private static Messenger instance;
public static Messenger Instance
{
get { return instance ?? (instance = new Messenger()); }
}
private Messenger() { }
public void SendMessage(Message message)
{
OnMessageSent temp = MessageSent;
if (temp != null)
temp(message);
}
public delegate void OnMessageSent(Message message);
public event OnMessageSent MessageSent;
}
The message-class looks like:
public class Message
{
public Type TargetType { get; set; }
public object Sender { get; set; }
public Type ValueType { get; set; }
public object Value { get; set; }
public string AdditionalInfo { get; set; }
}
The usage of this building is:
The receiver-viewmodel of a message has to add
Messenger.Instance.MessageSent += MessageSent;
to it's constructor. And in the implementation can look like:
private void MessageSent(Message message)
{
if(message.TargetType == typeof(SecondViewModel))
{
if (message.ValueType == typeof (double))
{
this.MyValue= (double) message.Value;
}
}
}
This works fine. My question is: Is this a good way for the communication between viewmodels or are there any weakenings in this design?
You don't need to re-invent the wheel when its already there.
Use EventAggregator which internally uses weak event pattern to prevent any memory leaks. Refer to tutorials here and here.
Also you can use Event Aggregator with Reactive Extensions.
Refer to the post for viable approaches you can reuse - Even Aggregator Implementation Sample/Best Practices.

Categories

Resources