Refactoring C# event based with SQL Server operations - c#

I am not sure how to decide about how to refactor some production code. This code works as select records top 1 from db and decided to column containing value under the below.
switch(column_value):
case send_email:
send_email.DoIt();
case enable_somexx:
enable_somexx.DoIt();
case response_email:
response_email.DoIt();
Showing the below examples, there are created classes for every events (records) including a DoIt() method(SendMail, DecideMail, ResponseMail, MailXXX, enable_somexx). The classes include 3 subfolders actions named action, decision, response (actually these classes irrelevant which other because code select top 1 record)
I'm thinking of refactoring this code logic like this:
Create base class named Behaviour
other 3 main classes will inherit from this base class
Code:
public abstract Behaviour
{
public virtual void DoIt(string type) {
}
}
--Also another classes Decision, Response will inherit from Behaviour.
public class Action : Behaviour
{
override void DoIt(string type) {
}
}
public class Email : Action
{
override void DoIt(string type)
{
if(type == SEND)
call_sendmethod
else if(xxx_operation_about_mail)
call_xxx_operation_about_mail
}
}
But I cannot handle (actually I don't like my solution because I don't want to create same class every operations like EmailAction, EmailResponse, EmailDecision or another operations)
If you make this code block refactoring, how would you do it?
Thank you.

Using your idea of refactoring ... this is how I would code it:
Here is an outline:
Create an abstract class for Behavior
Create an action class which inherits Behavior
Then you can code like this to trigger desire "action".
Notice how I override the "Send" behavior to customize it to "special sent".
Here is the fiddle: https://dotnetfiddle.net/m3tjWl
Blockquote
public class Program : Action
{
public static void Main()
{
Console.WriteLine("Hello World");
var command = Console.ReadLine();
//trigger send from Action class
Action x = new Action();
x.DoIt(command);
//trigger send from behavior class
//the lines below are added to show how you can still access the parent behavior, remove or use where appropriate
Behaviour y = x;
y.Send();
}
}
public abstract class Behaviour
{
public virtual void Send()
{
Console.WriteLine("sent");
}
public virtual void EnableX()
{
Console.WriteLine("enabled");
}
public virtual void Reply()
{
Console.WriteLine("replied");
}
public abstract void DoIt(string type);
}
public class Action : Behaviour
{
public override void DoIt(string type)
{
if(type.ToUpper() == "SEND")
this.Send();
else if (type.ToUpper() == "ENABLEX")
this.EnableX();
else if (type.ToUpper() == "REPLY")
this.Reply();
else
Console.WriteLine("Unknown Command");
}
new public void Send()
{
Console.WriteLine("Special Sent");
}
}

Related

Using OnBackPressedCallback in Xamarin

I'm trying to implement something similar to OnBackPressed() in a fragment in Xamarin, but the only solutions I found so far are for Java.
Here is one example in Java that does what I want:
OnBackPressedCallback callback = new OnBackPressedCallback(true) {
#Override
public void handleOnBackPressed() {
Toast.makeText(mContext, "back pressed", Toast.LENGTH_SHORT).show();
// And when you want to go back based on your condition
if (yourCondition) {
this.setEnabled(false);
requireActivity().onBackPressed();
}
}
};
How could I go about converting that piece of code into C#?
UPDATE
Create an interface for handling your event:
public interface IOnBackPressedHandler
{
bool OnBackPressed();
}
In your activity(below is just an example) setup your interface callback as follows
public class FragActivity : AppCompatActivity
{
public override void OnBackPressed()
{
Fragment fragment = SupportFragmentManager.FindFragmentById(Resource.Id.yourFragmentId);
if (!(fragment is IOnBackPressedHandler) || !((IOnBackPressedHandler)fragment).OnBackPressed()) {
base.OnBackPressed();
}
}
}
Finally, your fragment would look something like that :
public class SomeFragment : Fragment, IOnBackPressedHandler
{
public bool OnBackPressed()
{
//Callbacks will be received here.
return true;
}
}
Hope this makes it easier to understand. You can also make this method a part of your base Fragment mark it as virtual and then have all classes inherit this to keep overriding it...
OG answer:
Well you cannot have anonymous classes in C#, So just create a Class that inherits this Abstract class and you're good:
public class HandleOnBackPressedCallback : OnBackPressedCallback
{
public HandleOnBackPressedCallback(bool enabled) : base(enabled)
{
}
public override void HandleOnBackPressed()
{
Toast.MakeText(context, "back pressed", ToastLength.Long).Show();
// And when you want to go back based on your condition
if (yourCondition)
{
this.setEnabled(false);
requireActivity().onBackPressed();
}
}
}
Good luck!!

Explanation on how this works?

I have a pretty basic understanding of inheritance and so when using it there are a few moments like this where I find it difficult to understand what's fully happening and it probably doesn't help that I'm most likely not using it properly.
Anyways though I have these 3 classes
public abstract class EffectBase
{
public enum EffectType
{
harm,
help,
self
}
public EffectType type;
public float duration;
public void Activate()
{
Debug.Log("Activating effect");
ApplyEffect();
}
public abstract void ApplyEffect();
public abstract void End();
}
public class Player : MonoBehaviour
{
public List<EffectBase> effects = new List<EffectBase>();
void Update()
{
if (Input.GetKeyDown("q"))
{
Debug.Log("Q pressed");
AddEffect(new SpeedEffect());
}
}
public void AddEffect(EffectBase effect)
{
Debug.Log("Adding effect");
effects.Add(effect);
effect.Activate();
}
}
public class SpeedEffect : EffectBase
{
public override void ApplyEffect()
{
Debug.Log("Speed effect applied");
}
public override void End()
{
Debug.Log("Speed effect ended");
}
}
When I call the AddEffect method I pass a new instance of SpeedEffect (I think it's an instance) as the parameter and then in the AddEffect method I call the Activate method from it, however, in the SpeedEffect class, it doesn't have or override that method so I'm assuming it goes to the base class which does have it and continues and now here's where I get confused in the Activate method it calls the ApplyEffect method, but how does it know to call the one in the SpeedEffect class?
Despite not having an override for Activate() that method still exists in the SpeedEffect class, you just didn't need to write any code for it since its the same code so theres no need to duplicate it.
The code for Activate() calls the ApplyEffect() method for whatever class its being called from. In this case: EffectBase.Activate() and SpeedEffect.Activate() have the same code in terms of reading it, but they are not the same; EffectBase.ApplyEffect() and SpeedEffect.ApplyEffect() are two different methods and each are called from their respective classes.

Log manager class accessible to all classes

I've been struggling with this for a while... I have a programm written using the MVP pattern, I want to have a LogHandler class that must retrieve a string that corresponds to an ID provided in one of these methods, but it also needs to update the GUI, adding items to a listbox. So to simplyfy, imagine this:
if (name != "Peter")
{
Log.RegisterError(31, 4) //errorType, errorID
}
So in the Log class it would then get the string that matches the type and IDs provided and MessageBox it, but what if I want to add that string to a control on the form? I'm using views implemented by the forms to accomplish GUI updating, but since this is a static class I can't...
Also where should errors be checked and raised? Presenter? View? Model?
Thanks in advance
You could add callbacks in you Log class that other object could subscribe to.
Example:
In this example the Presenter can listen for an error code to be logged then receive the error string from the Log from the Model class
public class Logger
{
private static Dictionary<int, List<Action<string>>> _callbacks = new Dictionary<int,List<Action<string>>>();
public static void RegisterLoggerCallback(int errorType, Action<string> callback)
{
// Just using errortype in this exaple, but the key can be anything you want.
if (!_callbacks.ContainsKey(errorType))
{
_callbacks.Add(errorType, new List<Action<string>>());
}
_callbacks[errorType].Add(callback);
}
public static void RegisterLog(int errorType, int errorID)
{
// find error sring with codes
string error = "MyError";
// show messagebox
MessageBox.Show(error);
// tell listeners
if (_callbacks.ContainsKey(errorType))
{
_callbacks[errorType].ForEach(a => a(error));
}
}
}
public class Model
{
public Model()
{
}
public void DoSomething()
{
Logger.RegisterLog(1, 2);
}
}
public class Presenter
{
public Presenter()
{
Logger.RegisterLoggerCallback(1, AddToListbox);
}
private void AddToListbox(string error)
{
// add to listbox when errortype 1 is called somewhere
}
}
This is a very simple example but should give you an idea of a way to achive this.

How to stop base static events/actions firing in other derived classes

I am working on an LOB application in C# using a WinForms tabbed MDI interface. I have various forms with DataGridViews to allow the user to select an object they are interested in, which they can then view/edit in a new form.
Each of my main business objects inherit from Entity, which is defined as below:
public abstract class Entity
{
public static event Action Saved;
internal virtual void OnSaved()
{
if (Saved != null)
{
Saved();
}
}
}
I then have the objects that populate the grid (these are actually auto-generated classes from Linq-to-SQL, although I can replicate the problem with normal classes):
class Class1 : Entity
{
//Stuff
}
class Class2 : Entity
{
//Stuff
}
I want to know when an object of a given class is modified, but i don't care which instance (hence the static action) so that i can refresh the grid and perform other activities.
The problem comes when the event is fired from a derived class instance - it fires for all other derived classes too. For example:
Class1.Saved += new Action(s1);
Class2.Saved += new Action(s2);
private void TestIt()
{
Class2 o2 = new Class2();
o2.OnSaved();
}
This would fire s1 and s2, but I only want the specific one to be fired (i.e. s2). What is the best way to do this? I have quite a few classes that need this behviour and would like to avoid having to add any code to each class if possible.
Update:
Thank you for all your responses, they have been very helpful.
I have opted for a slightly different option, which I admit seems quite hacky, but works well for my purposes. This involves passing the type with the action and letting a handler filter and call relevant operations.
Entity Class:
public abstract class Entity
{
public static event Action<Type> Saved;
internal void OnSaved()
{
private Action<Type> SavedCopy = Saved;
if (SavedCopy != null)
SavedCopy(this.GetType());
}
}
Hook up handler:
Entity.Saved += new Action<Type>(Handler);
Example Handler method (this will vary from form to form):
void Handler(Type obj)
{
if (obj==typeof(Class1))
UpdateGrid();
else if (obj==typeof(Class2))
UpdateBasicInfo();
else if (obj == typeof(Class3))
DoAnotherThing();
}
Using generics could be a work around; each generic class gets a copy of the static fields.
public abstract class Entity<T>
{
public static event Action Saved = delegate { };
internal virtual void OnSaved()
{
Saved();
}
}
class Class1 : Entity<Class1>
{
//Stuff
}
class Class2 : Entity<Class2>
{
//Stuff
}
I'm not sure doing it like this is a good idea, but you could specify the type when you subscribe and when you save the data:
public abstract class Entity
{
private static Dictionary<Type, Action> Subscribers
= new Dictionary<Type, Action>();
internal virtual void OnSaved()
{
OnSaved(GetType());
}
private OnSaved(Type type)
{
Action subscribed;
Subscribers.TryGetValue(type, out subscribed);
if (subscribed != null)
subscribed();
}
public Subscribe(Type type, Action action)
{
Action subscribed;
Subscribers.TryGetValue(type, out subscribed);
Subscribers[type] = subscribed + action;
}
public Unsubscribe(Type type, Action action)
{
Action subscribed;
Subscribers.TryGetValue(type, out subscribed);
Subscribers[type] = subscribed - action;
}
}
Keep in mind that this code is not thread-safe, so if you want to use it from different threads at the same time, you need to add locking.
You will need to have an event per type, because can't determine for which type the delegate is registered when the event is defined on the base type.
public abstract class Entity
{
internal abstract void OnSaved();
}
class Class1 : Entity
{
public static event Action Saved = () => { };
internal override void OnSaved()
{
this.Saved();
}
//Stuff
}
class Class2 : Entity
{
public static event Action Saved = () => { };
internal override void OnSaved()
{
this.Saved();
}
//Stuff
}
Why does it have to be static? Make it an instance event instead.
public event Action Saved;
You have to hook it up for each instance instead of just once per class (or, in your current case, once), but it will separate the events.

C# Events handling problem for base and derived classes

I have this case where I'm creating 2 different event handlers placed in a base class and subscribing to them accordingly from Quotes and Charts classes. Problem I'm having is that the first subscription triggers fine for the first event but any following subscriptions don't get executed. I have included an example of 2 different handlers, Quotes and Charts, Quotes executes first time with no problems, but Charts does not trigger when data is received.
Base Class:
public abstract class MyBaseClass
{
protected virtual void RaiseOnQuoteData(string item) { }
protected virtual void RaiseOnChartData(string item) { }
void OnDataReceived(object sender, DataEventArgs e)
{
if (e.Item == "QUOTE")
RaiseOnQuoteData(e.Item);
else if (e.Item == "CHART")
RaiseOnChartData(e.Item);
}
}
Quote and Chart Classes:
public class Quote : MyBaseClass
{
public event EventHandler<DataEventArgs<quoteRecord>> OnQuoteData;
protected override void RaiseOnQuoteData(string item)
{
OnQuoteData.Raise<DataEventArgs<quoteRecord>>(this, new DataEventArgs<quoteRecord>(item));
}
}
public class Chart : MyBaseClass
{
public event EventHandler<DataEventArgs<chartRecord>> OnChartData;
protected override void RaiseOnChartData(string item)
{
OnChartData.Raise<DataEventArgs<chartRecord>>(this, new DataEventArgs<chartRecord>(item));
}
}
Subscription:
public class QuoteSubscription
{
public static void SubscribetoQuoteData()
{
Quote Q = new Quote();
Q.OnQuoteData += new EventHandler<DataEventArgs<quoteRecord>>(q_OnQuoteData);
}
static void q_OnQuoteData()
{
//Executes fine
}
}
public class ChartSubscription
{
public static void SubscribetoChartData()
{
Chart C = new Chart();
C.OnChartData += new EventHandler<DataEventArgs<chartRecord>>(q_OnChartData);
}
static void q_OnChartData()
{
//Does not execute
}
}
This is implemented in ASP.NET 4.0, Is there any chance that instantiating the derived classes could be the problem since both classes do share the same base class? Any help pointing to the cause would be greatly appreciated.
What is there in Raise? This must be an extension method, since EventHandler per se doesn't define such a method. Therefore, you can put a breakpoint inside and see, what's going on. (And you could perhaps put a breakpoint inside RaiseOnChartData as well.)
Could it be that you are creating the object within the method scope and has gone out of scope. You may get the first message by coincidence just because it hasn't been GC-ed. Try creating the quote and chart objects as static class member object

Categories