Get permitted triggers with guard conditions in Stateless (.NET state machine library) - c#

Background:
I have same Trigger with mutually exclusive guard conditions defined with PermitIf that will cause transition to different states depending on those conditions.
Guards have Descriptions defined and they show up nicely in brackets in exported DOT graph, so it is easy to follow through.
machine
.Configure(Status.Registered)
.PermitIf(Activity.Submit, Status.Submitted, IsGoodRating, "Is good rating")
.PermitIf(Activity.Submit, Status.Denied, IsBadRating, "Is bad rating")
Now, I know there is machine.PermittedTriggers property that returns allowed Triggers in current state which is great, but here is the question.
Question :
Is there a way to get a list of PermittedTriggers with corresponding guard conditions for status Registered in this case?

I guess you could do something like this, but... I don't know how helpful it is:
class Program
{
enum Status { Registered, Submitted, Denied }
static void Main(string[] args)
{
int currentRating = 91;
RatingTrigger RatingTrigger = new RatingTrigger();
StateMachine<Status, Trigger> _sm = new StateMachine<Status, Trigger>(Status.Registered);
_sm.Configure(Status.Registered)
.PermitIf(RatingTrigger, Status.Submitted, () => RatingTrigger.Guard(currentRating), RatingTrigger.GuardDescription)
.PermitIf(RatingTrigger, Status.Denied, () => RatingTrigger.Guard(currentRating), RatingTrigger.GuardDescription);
var list = _sm.PermittedTriggers;
foreach (var item in list)
{
if (item.GetType().Equals(typeof(RatingTrigger)))
{
Console.WriteLine(((RatingTrigger)item).GuardDescription);
}
else
Console.WriteLine(item);
}
}
private static bool evaluate()
{
return true;
}
}
public abstract class Trigger
{
public abstract bool Guard(object something);
}
public class RatingTrigger : Trigger
{
public string GuardDescription = "This Guard evaluaties the current rating. Retuns true if good rating, false if bad rating";
public override bool Guard(object rating)
{
return (((int)rating) > 90);
}
}

Related

Does Instantiating new instance make all code thread safe?

Edited the code to make it thread-safe post comments
Please see the updated question at the end.
Can you please help me understand if this code is thread-safe or how it can be made thread safe?
Setup
My system has a very simple class called WorkItem.
public class WorkItem
{
public int Id {get;set;}
public string Name {get;set;}
public DateTime DateCreated {get;set;}
public IList<object> CalculatedValues {get;set;}
}
There is an interface ICalculator which has a method that takes a work item, performs a calculation and returns true.
public interface ICalculator
{
bool Calculate(WorkItem WorkItem);
}
Let's say we have two implementations of ICalculator.
public class BasicCalculator: ICalculator
{
public bool Calculate(WorkItem WorkItem)
{
//calculate some value on the WorkItem and populate CalculatedValues property
return true;
}
}
Another calculator:
public class AnotherCalculator: ICalculator
{
public bool Calculate(WorkItem WorkItem)
{
//calculate some value on the WorkItem and populate CalculatedValues property
//some complex calculation on work item
if (somevalue==0) return false;
return true;
}
}
There is a calculator handler class. Its responsibility is to execute calculators sequentially.
public class CalculatorHandler
{
public bool ExecuteAllCalculators(WorkItem task, ICalculator[] calculators)
{
bool final = true;
//call all calculators in a loop
foreach(var calculator in calculators)
{
var calculatedValue = calculator.Calculate(WorkItem);
final = final && calculatedValue;
}
return final;
}
}
Finally, in my client class, I inject ICalculators[] which are relevant for the run. I then instantiate ExecuteCalculators() method.
Now I have a large number of work items and I want to perform calculations on them so I create a list of Task, where each task is responsible of instantiating CalculatorHandler instance and then takes a work item and performs calculations by doing a WaitAll() on all of the tasks, e.g.
public class Client
{
private ICalculators[] _myCalculators;
public Client(ICalculators[] calculators)
{
_myCalculators = calculators;
}
public void ExecuteCalculators()
{
var list = new List<Task>();
for(int i =0; i <10;i++)
{
Task task = new Task(() =>
var handler = new CalculatorHandler();
var WorkItem = new WorkItem(){
Id=i,
Name="TestTask",
DateCreated=DateTime.Now
};
var result = handler.ExecuteAllCalculators(WorkItem, _myCalculators);
);
list.Add(task);
}
Task.WaitAll(list);
}
}
This is a simplied version of the system. Actual system has a range of calculators and Calculators and CalculatorHandler are injected via IoC etc.
My questions are - help me understand these points:
Each task creates a new instance of CalculatorHandler. Does this
mean anything that happens in CalculatorHandler is thread safe as it
does not have any public properties and simply loops over
calculators?
Calculators are shared amongst all tasks because they are member variable of Client class but they are passed into
CalculatorHandler which is instantiated for each task. Does it mean that when all tasks run, as new
instance of CalculatorHandler is created therefore Calculators are
automatically thread safe and we will not experience any threading issues e.g. deadlocks etc?
Can you please suggest how I can make the code threadsafe? Is it
best to pass in a Func<'ICalculators>'[] to Client class and then within each task, we can execute Func<'ICalculator'>() and then pass those instances to ICalculator there? Func<'ICalculator'> will return instance of ICalculator.
Is it true that calculators are passed in as private method variable therefore other instances of CalulatorHandler cannot run the same instance of calculator? Or because calculators are reference types, we are bound to get multi thread issues?
Update
Can you please help me understand if this updated code is thread-safe or how it can be made thread safe?
Setup
My system has a very simple class called WorkItem. It has getter public properties except 1 property "CalculatedValues".
public class WorkItem
{
public int Id {get;}
public string Name {get;}
public DateTime DateCreated {get;}
public IList<object> CalculatedValues {get;set;}
public WorkItem(int id, string name, DateTime dateCreated)
{
Id = id,
Name = name,
DateCreated = dateCreated
}
}
There is an interface ICalculator which has a method that takes a work item, performs a calculation and returns a IList. It does not change the state of work item.
public interface ICalculator
{
IList<object> Calculate(WorkItem WorkItem);
}
Let's say we have two implementations of ICalculator.
public class BasicCalculator: ICalculator
{
public IList<object>Calculate(WorkItem WorkItem)
{
//calculate some value and return List<object>
return List<object>{"A", 1};
}
}
Another calculator:
public class AnotherCalculator: ICalculator
{
public bool Calculate(WorkItem WorkItem)
{
//calculate some value and return List<object>
return List<object>{"A", 1, workItem.Name};
}
}
There is a calculator handler class. Its responsibility is to execute calculators sequentially. Note, it takes in ICalculators in its constructor when it is instantiated. It has a private static lock object too when it updates work item instance.
public class CalculatorHandler
{
private ICalculators[] _calculators;
public CalculatorHandler(ICalculators[] calculators)
{
_calculators = calculators;
}
//static lock
private static object _lock = new object();
public bool ExecuteAllCalculators(WorkItem workItem, ICalculator[] calculators)
{
bool final = true;
//call all calculators in a loop
foreach(var calculator in calculators)
{
var calculatedValues = calculator.Calculate(workItem);
//within a lock, work item is updated
lock(_lock)
{
workItem.CalculatedValues = calculatedValues;
}
}
return final;
}
}
Finally, in my client class, I execute CalculatorHandler.
Now I have a large number of work items and I want to perform calculations on them so I create a list of Task, where each task is responsible of instantiating CalculatorHandler instance and then takes a work item and performs calculations by doing a WaitAll() on all of the tasks, e.g.
public class Client
{
public void ExecuteCalculators()
{
var list = new List<Task>();
for(int i =0; i <10;i++)
{
Task task = new Task(() =>
//new handler instance and new calculator instances
var handler = new CalculatorHandler(new[]{
new BasicCalculator(), new AnotherCalculator()
});
var WorkItem = new WorkItem(
i,
"TestTask",
DateTime.Now
};
var result = handler.ExecuteAllCalculators(WorkItem);
);
list.Add(task);
}
Task.WaitAll(list);
}
}
This is a simplied version of the system. Actual system has a range of calculators and Calculators and CalculatorHandler are injected via IoC etc.
My questions are - help me understand these points:
Each task creates a new instance of CalculatorHandler and new instances of ICalculators. Calculators do not perform any I/O operations and only create a new private IList. Is calculator handler and calculator instances now thread safe?
CalculatorHandler updates work item but within a lock. Lock is a static private object. Does it mean all instances of CalculatorHandler will share one single lock and therefore at one point, only one thread can update the work item?
Work item has all public getter properties except its CalculatedValues property. CalculatedValues is only set within a static lock. Is this code now thread-safe?
1) Creating a new instance of a class, even one without public properties does not provide any guarantee of thread safety. The problem is that ExecuteAllCalculators takes two object parameters. The WorkItem object contains mutable properties and the same WorkItem object is used for all ICalculator calls. Suppose one of the calculators decides to call Clear() on WorkItem.CalculatedValues. Or suppose one calculator sets WorkItem.Name to null and the next decides to do a WorkItem.Name.Length. This isn't technically a "threading" issue because those problems can occur without multiple threads involved.
2) Calculator objects shared across threads is definitely not thread safe. Suppose one of the calculator instances uses a class level variable. Unless that variable is somehow thread protected (example: lock {...}), then it would be possible to produce inconsistent results. Depending how "creative" the implementer of the calculator instances were a deadlock could be possible.
3) Any time your code accepts interfaces you are inviting people to "play in your sandbox". It allows code that you have little control of to be executed. One of the best ways to handle this is to use immutable objects. Unfortunately, you can't change the WorkItem definition without breaking your interface contract.
4) Calculators are passed by reference. The code shows that _myCalculators is shared across all tasks created. This doesn't guarantee that you will have problems, it only makes it possible that you might have problems.
No, it is not thread-safe. If there is any shared state in any calculation then the it is possible to have threading issues. The only way to avoid threading issues is to ensure you are not updating any shared state. That means read-only objects and/or using "pure" functions.
You've used the word "shared" - that means not thread-safe by virtue of sharing state. Unless you mean "distributed" rather than "shared".
Exclusively use read-only objects.
They are reference types so they may be shared amongst separate threads - hence not thread-safe - unless they are read-only.
Here's an example of a read-only object:
public sealed class WorkItem : IEquatable<WorkItem>
{
private readonly int _id;
private readonly string _name;
private readonly DateTime _dateCreated;
public int Id { get { return _id; } }
public string Name { get { return _name; } }
public DateTime DateCreated { get { return _dateCreated; } }
public WorkItem(int id, string name, DateTime dateCreated)
{
_id = id;
_name = name;
_dateCreated = dateCreated;
}
public override bool Equals(object obj)
{
if (obj is WorkItem)
return Equals((WorkItem)obj);
return false;
}
public bool Equals(WorkItem obj)
{
if (obj == null) return false;
if (!EqualityComparer<int>.Default.Equals(_id, obj._id)) return false;
if (!EqualityComparer<string>.Default.Equals(_name, obj._name)) return false;
if (!EqualityComparer<DateTime>.Default.Equals(_dateCreated, obj._dateCreated)) return false;
return true;
}
public override int GetHashCode()
{
int hash = 0;
hash ^= EqualityComparer<int>.Default.GetHashCode(_id);
hash ^= EqualityComparer<string>.Default.GetHashCode(_name);
hash ^= EqualityComparer<DateTime>.Default.GetHashCode(_dateCreated);
return hash;
}
public override string ToString()
{
return String.Format("{{ Id = {0}, Name = {1}, DateCreated = {2} }}", _id, _name, _dateCreated);
}
public static bool operator ==(WorkItem left, WorkItem right)
{
if (object.ReferenceEquals(left, null))
{
return object.ReferenceEquals(right, null);
}
return left.Equals(right);
}
public static bool operator !=(WorkItem left, WorkItem right)
{
return !(left == right);
}
}
Once created it can't be modified so thread-safety is no longer an issue.
Now, if I can assume that each ICalculator is also implemented without state, and thus is a pure function, then the calculation is thread-safe. However, there is nothing in your question that let's me know that I can make this assumption. There is no way, because of that, that anyone can tell you that your code is thread-safe.
So, given the read-only WorkItem and the pure ICalculator function, then the rest of your code then looks like it would be perfectly fine.

How to reset delegate to original code

given this delegate
public class XYZ
{
public static Action<Profile> DoSomething = (profile) =>
{
//some default code here
return;
};
}
at some time in my main execution I override it with this:
XYZ.DoSomething = (currProfile) =>
{
// some overriding code here
}
How do I set the code back to the original default code when I need to without duplicating code?
Here's a good reason to never use public fields...
Once you set it; its gone. You can hold onto the original value though:
var originalAction = XYZ.DoSomething;
XYZ.DoSomething = ...;
XYZ.DoSomething = originalAction;
Usually it is a bad idea to rely on client code to handle this however; so if I was writing it I would expose as a property like so:
public Action<X> DoSomethingOverride {get; set;}
public Action<X> DoSomething => doSomethingOverride ?? DefaultMethod;
private void DefaultMethod (X param)
{
}
There are a number of other ways to handle this, but all involve storing off the original method. All good ways to handle this will use a property to ensure that only the declaring class is actually setting the DoSomething method and that resetting to the default is possible.
Total aside; since this is static setting the action will affect everything that uses this class. This is asking for bugs later; don't do that.
Maybe somthing like this?
public static Action<Profile> _doSomethingBase = (profile) =>
{
//some default code here
return;
};
public static Action<Profile> _doSomething = _doSomethingBase;
public static Action<Profile> DoSomething
{
get => _doSomething;
set => _doSomething = value;
}
public static void RevertDoSomething()
{
DoSomething = _doSomethingBase;
}

How to store a list of Cases from Switch Statement?

In my program I have a listbox that when the user double clicks an object it looks to a switch statement to see what event should occur. As the list begins getting larger I'm curious if there is a way to avoid having to maintain the list of objects in 2 places (once in a list to Add to the listbox, and once in the switch statement.
Is there a way to index/read/store the various Cases of my switch statement, then add them as objects to my listbox?
Example: (doesn't work, just a theory)
Switch (n)
ForEach (Case c in Cases)
{
arrayCases.Add(c);
}
listbox.Items.AddRange(arrayCases);
EDIT:
Going on the Dictionary recommendations I now have:
public void SetDictionary()
{
//add entries to the dictionary
dict["cat"] = new Action(Cat);
dict["dog"] = new Action(Dog);
//add each dictionary entry to the listbox.
foreach (string key in dict.Keys)
{
listboxTest.Items.Add(key);
}
}
//when an item in the listbox is double clicked
private void listboxTest_DoubleClick(object sender, EventArgs e)
{
testrun(listboxCases.SelectedItem.ToString());
}
public void testrun(string n)
{
//this is supposed to receive the item that was double clicked in the listbox, and run it's corresponding action as defined in the dictionary.
var action = dict[n] as Action action();
}
I believe that my code above is mostly correct and that I'm understanding it, however the action line:
var action = dict[n] as Action action();
Shows an error stating 'action' is expecting a ';'. Is my logic here accurate? If so, why is the action call incorrect?
Dictionary<string, Action> is the way to avoid. Dictionary.Keys becomes ListBox.Items.
switch(n) becomes
var action = dict[n] as Action
action();
I suggest to move your operations into separate classes. Create a base class for your operations like the following one. I added a field for the form because you probably have to interact with your form. You can also pass in other objects if required.
internal abstract class Operation
{
protected readonly MyForm form = null;
protected Operation(MyForm form)
{
this.form = form;
}
public abstract String DisplayName { get; }
internal abstract void Execute();
}
Then derive one class for each operation.
internal sealed class DoThis : Operation
{
internal DoThis(MyForm form) : base(form) { }
public override String DisplayName
{
get { return "Do this!"; }
}
internal override void Execute()
{
// Code to do this. You can use this.form to interact with
// your form from this operation.
}
}
internal sealed class DoSomethingElse : Operation
{
internal DoSomethingElse(MyForm form) : base(form) { }
public override String DisplayName
{
get { return "Do something else!"; }
}
internal override void Execute()
{
// Code to do something else.
}
}
Now you can add all your operations to the list box
this.lsitBox.Items.Add(new DoThis(this));
this.lsitBox.Items.Add(new DoSomethingElse(this));
and set the display member property.
this.listBox.DisplayMember = "DisplayName";
Finally execute the selected operation in the event handler.
((Operation)this.listBox.SelectedItem).Execute();
This pattern gives clean separation between all your operations and makes future extensions easy and clean. For example you could add a property CanExecute to all operations if you have to check if a operation is currently available. Or if you have to support localization it is easy to add logic for presenting the name of the operation in the current UI language.
Another scenario that is easily supported is if you have some code common to all operations for example logging, security checks, performance measuring and things like that.
internal abstract class Operation
{
protected readonly MyForm form = null;
protected Operation(MyForm form)
{
this.form = form;
}
public abstract String DisplayName { get; }
protected abstract void ExecuteCore();
internal void Execute()
{
Logger.Log("Executing operation " + this.DisplayName);
try
{
this.ExecuteCore();
Logger.Log("Executing operation " + this.DisplayName + " succeeded.");
}
catch (Exception exception)
{
Logger.Log("Executing operation " + this.DisplayName + " failed.", exception);
throw;
}
}
}
Note that you now have to override ExecuteCore() instead of Execute().
One final thought - using an interface IOperation instead or in combination with the abstract base class may be helpful, too. This removes the need that all operation inherit from the same base class because this might sometimes be inconvenient. But I omitted this to not overengineere this even more.
You can't* enumerate case of switch with normal code.
What you can do instead is to replace switch with map of "action name" to "action handler" and than you'll be able to reuse this map for list of action names listbox. See Tilak's answer for sample.
*) If you are really inquisitive you can enumerate choices of switch. C# code is transformed to IL and IL can be read with code. So you can get IL for a method, write (or get existing - Parser for C#) parser for IL and find implementation of switch inside the method, pick all cases. You can even go straight to C# source at build time - but it is even more involved than IL parsing.
Yes there is a way to do this by making a dictionary of lambdas.
void Main()
{
// set up your dictionary
Dictionary<string,Action> myList = new Dictionary<string,Action> {
{ "one", () => { Console.WriteLine("One function"); } },
{ "two", () => { Console.WriteLine("Two function"); }},
{ "three", () => { Console.WriteLine("Three function"); }}
};
// do a "switch" (that is invoke a function that corresponds to a name)
myList["one"]();
// loop the list of keys (that is get a list of all the names)
foreach (string key in myList.Keys)
Console.WriteLine(key);
}
the output of this program:
One function
one
two
three
Also note -- you can add to this "switch" dynamically like this (which is cool and something you can't do with a classical switch statement.)
myList.Add("four",() => { Console.WriteLine("Four function is dynamic"); });
It sounds to me like the number of cases in your switch are going to change a lot. If this is true, then you might want to consider using a mechanism other than a switch statement. Perhaps you want to do something like Alexi Levenkov suggests, and then iterate a list of the stored Action Names and execute the associated handler. This way you will avoid having to add the action name to the action map and then add it to the switch.

Using a returned error message to determine if error is present

I was recently talking with a buddy about return values taking only a single meaning. At my previous job, we worked with C++ and had typedef'ed wBOOL so that a 0 was wFALSE, and 1 was wTRUE. The architect said that we can also return 2, 3, 4... for more information, which I think is a horrible idea. If we expect wTRUE = 1 and wFALSE = 0 and wBOOL = {wTRUE, wFALSE}, returning anything else should be avoided... now, on to today's C#.
I recently reviewed a piece of code where there were a collection of functions that determined if there was an error and returned the string back to the user:
private bool IsTestReady(out string errorMessage)
{
bool isReady = true;
errorMessage = string.Empty;
if(FailureCondition1)
{
isReady = false;
errorMessage = FailureMessage1;
}
else if(FailureCondition2)
{
isReady = false;
errorMessage = FailureMessage2;
}
//... other conditions
return isReady;
}
Then, to use these functions...
private enum Tests
{ TestA, TestB, TestC }
private void UpdateUI()
{
string error = string.Empty;
bool isTestReady;
switch(this.runningTest) // which test are we running (TestA, TestB, or TestC)
{
case Tests.TestA:
isTestReady = IsTestAReady(error);
break;
case Tests.TestB:
isTestReady = IsTestBReady(error);
break;
case Tests.TestC:
isTestReady = IsTestCReady(error);
break;
}
runTestButton.Enabled = isTestReady;
runTestLabel.Text = error;
}
I thought to separate these out into two methods:
private string GetTestAErrorMessage()
{
//same as IsTestReady, but only returns the error string, no boolean stuffs
}
private bool IsTestAReady
{
get{ return string.IsNullOrEmpty(GetTestAErrorMessage()); }
}
Does this violate the principal of not having a return value mean more than one thing? For instance, in this case, if there error message IsNullOrEmpty, then there is no error. I think that this does not violate that principal; my co-worked does. To me, it's no different than this:
class Person
{
public int Height {get;}
public bool IsTall() { return Height > 10; }
}
Any thoughts or suggestions on a different approach to this issue? I think the out parameter is the worst of the solutions.
The return value and the error message are technically not bound together. You could have a developer come along at a later time and add a new failure condition to IsTestReady, and that failure condition may not set an error message. Or, perhaps there is a message, but it doesn't exactly represent a failure (like, perhaps a warning or something), so the error message parameter may get set, but the return value is true.
An exception doesn't really work in this case either, for the exact reason that StriplingWarrior wrote in his comment - exceptions should be used for non-normal operational states, and a non-ready test is a normal state.
One solution might be to remove the error message parameter and have the IsTestReady function return a class:
public class TestReadyResult {
public bool IsReady { get; set; }
public string Error { get; set; }
}
There is just one property to check - TestReadyResult.IsReady - for test state, and if necessary, the Error property can be used for non-ready states. There is no extra parameter to manage for the function call, either.
I'm not a big fan of having the null or empty return value indicate that nothing is wrong. A better comparison than the one you gave is:
class Person
{
public int Height {get;}
public bool IsBorn() { return Height > 0; }
}
In .NET, it is common practice to use the "bool return with out parameter" pattern you see in your original method (see the various TryParse methods, for example). However, if you prefer, another solution would be to create a TestReadyCheck class with both the boolean and the string as properties. I've done something similar with the following class, and been quite happy with it.
public class RequestFilterResult
{
public static readonly RequestFilterResult Allow = new RequestFilterResult(true, null);
public static RequestFilterResult Deny(string reason) { return new RequestFilterResult(false, reason); }
protected RequestFilterResult(bool allowRequest, string denialReason)
{
AllowRequest = allowRequest;
DenialReason = denialReason;
}
public bool AllowRequest { get; private set; }
public string DenialReason { get; private set; }
}
This allows for the following usage:
public RequestFilterResult Filter(...)
{
if (FailureCondition1) return RequestFilterResult.Deny(FailureMessage1);
if (FailureCondition2) return RequestFilterResult.Deny(FailureMessage2);
return RequestFilterResult.Allow();
}
It's concise, while enforcing that failure results provide a failure message, and success results don't.
On a side note, the structure of your switch statement feels like a code smell to me. You may want to consider ways to leverage polymorphism. Maybe make each test have its own class, with an IsTestReady method on it?
I would use exceptions to convey information about failure states, rather than relying on the caller to know how to use an error message field (even though it's private).

c# marking class property as dirty

The following is a simple example of an enum which defines the state of an object and a class which shows the implementation of this enum.
public enum StatusEnum
{
Clean = 0,
Dirty = 1,
New = 2,
Deleted = 3,
Purged = 4
}
public class Example_Class
{
private StatusEnum _Status = StatusEnum.New;
private long _ID;
private string _Name;
public StatusEnum Status
{
get { return _Status; }
set { _Status = value; }
}
public long ID
{
get { return _ID; }
set { _ID = value; }
}
public string Name
{
get { return _Name; }
set { _Name = value; }
}
}
when populating the class object with data from the database, we set the enum value to "clean". with the goal of keeping most of the logic out of the presentation layer, how can we set the enum value to "dirty" when a property is changed.
i was thinking something along the lines of;
public string Name
{
get { return _Name; }
set
{
if (value != _Name)
{
_Name = value;
_Status = StatusEnum.Dirty;
}
}
}
in the setter of each property of the class.
does this sound like a good idea, does anyone have any better ideas on how the dirty flag can be assigned without doing so in the presentation layer.
When you really do want a dirty flag at the class level (or, for that matter, notifications) - you can use tricks like below to minimise the clutter in your properties (here showing both IsDirty and PropertyChanged, just for fun).
Obviously it is a trivial matter to use the enum approach (the only reason I didn't was to keep the example simple):
class SomeType : INotifyPropertyChanged {
private int foo;
public int Foo {
get { return foo; }
set { SetField(ref foo, value, "Foo"); }
}
private string bar;
public string Bar {
get { return bar; }
set { SetField(ref bar, value, "Bar"); }
}
public bool IsDirty { get; private set; }
public event PropertyChangedEventHandler PropertyChanged;
protected void SetField<T>(ref T field, T value, string propertyName) {
if (!EqualityComparer<T>.Default.Equals(field, value)) {
field = value;
IsDirty = true;
OnPropertyChanged(propertyName);
}
}
protected virtual void OnPropertyChanged(string propertyName) {
var handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
You might also choose to push some of that into an abstract base class, but that is a separate discussion
One option is to change it on write; another is to keep a copy of all the original values and compute the dirtiness when anyone asks for it. That has the added benefit that you can tell exactly which fields have changed (and in what way) which means you can issue minimal update statements and make merge conflict resolution slightly easier.
You also get to put all the dirtiness-checking in one place, so it doesn't pollute the rest of your code.
I'm not saying it's perfect, but it's an option worth considering.
If you want to implement it in this way, and you want to reduce the amount of code, you might consider applying Aspect Oriented Programming.
You can for instance use a compile-time weaver like PostSharp , and create an 'aspect' that can be applied to properties. This aspect then makes sure that your dirty flag is set when appropriate.
The aspect can look like this:
[Serializable]
[AttributeUsage(AttributeTargets.Property)]
public class ChangeTrackingAttribute : OnMethodInvocationAspect
{
public override void OnInvocation( MethodInvocationEventArgs e )
{
if( e.Delegate.Method.ReturnParameter.ParameterType == typeof(void) )
{
// we're in the setter
IChangeTrackable target = e.Delegate.Target as IChangeTrackable;
// Implement some logic to retrieve the current value of
// the property
if( currentValue != e.GetArgumentArray()[0] )
{
target.Status = Status.Dirty;
}
base.OnInvocation (e);
}
}
}
Offcourse, this means that the classes for which you want to implement ChangeTracking, should implement the IChangeTrackable interface (custom interface), which has at least the 'Status' property.
You can also create a custom attribute ChangeTrackingProperty, and make sure that the aspect that has been created above, is only applied to properties that are decorated with this ChangeTrackingProperty attribute.
For instance:
public class Customer : IChangeTrackable
{
public DirtyState Status
{
get; set;
}
[ChangeTrackingProperty]
public string Name
{ get; set; }
}
This is a little bit how I see it.
You can even make sure that PostSharp checks at compile-time whether classes that have properties that are decorated with the ChangeTrackingProperty attribute, implement the IChangeTrackable interface.
This method is based on a set of different concepts provided in this thread. I thought i'd put it out there for anyone that is looking for a way to do this cleanly and efficiently, as i was myself.
The key of this hybrid concept is that:
You don't want to duplicate the data to avoid bloating and resource hogging;
You want to know when the object's properties have changed from a given original/clean state;
You want to have the IsDirty flag be both accurate, and require little processing time/power to return the value; and
You want to be able to tell the object when to consider itself clean again. This is especially useful when building/working within the UI.
Given those requirements, this is what i came up with, and it seems to be working perfectly for me, and has become very useful when working against UIs and capturing user changes accurately. I have also posted an "How to use" below to show you how I use this in the UI.
The Object
public class MySmartObject
{
public string Name { get; set; }
public int Number { get; set; }
private int clean_hashcode { get; set; }
public bool IsDirty { get { return !(this.clean_hashcode == this.GetHashCode()); } }
public MySmartObject()
{
this.Name = "";
this.Number = -1;
MakeMeClean();
}
public MySmartObject(string name, int number)
{
this.Name = name;
this.Number = number;
MakeMeClean();
}
public void MakeMeClean()
{
this.clean_hashcode = this.Name.GetHashCode() ^ this.Number.GetHashCode();
}
public override int GetHashCode()
{
return this.Name.GetHashCode() ^ this.Number.GetHashCode();
}
}
It's simple enough and addresses all of our requirements:
The data is NOT duplicated for the dirty check...
This takes into account all property changes scenarios (see scenarios below)...
When you call the IsDirty property, a very simple and small Equals operation is performed and it is fully customizable via the GetHashCode override...
By calling the MakeMeClean method, you now have a clean object again!
Of course you can adapt this to encompass a bunch of different states... it's really up to you. This example only shows how to have a proper IsDirty flag operation.
Scenarios
Let's go over some scenarios for this and see what comes back:
Scenario 1
New object is created using empty constructor,
Property Name changes from "" to "James",
call to IsDirty returns True! Accurate.
Scenario 2
New object is created using paramters of "John" and 12345,
Property Name changes from "John" to "James",
Property Name changes back from "James" to "John",
Call to IsDirty returns False. Accurate, and we didn't have to duplicate the data to do it either!
How to use, a WinForms UI example
This is only an example, you can use this in many different ways from a UI.
Let's say you have a two forms ([A] and [B]).
The first([A]) is your main form, and the second([B]) is a form that allows the user to change the values within the MySmartObject.
Both the [A] and the [B] form have the following property declared:
public MySmartObject UserKey { get; set; }
When the user clicks a button on the [A] form, an instance of the [B] form is created, its property is set and it is displayed as a dialog.
After form [B] returns, the [A] form updates its property based on the [B] form's IsDirty check. Like this:
private void btn_Expand_Click(object sender, EventArgs e)
{
SmartForm form = new SmartForm();
form.UserKey = this.UserKey;
if(form.ShowDialog() == DialogResult.OK && form.UserKey.IsDirty)
{
this.UserKey = form.UserKey;
//now that we have saved the "new" version, mark it as clean!
this.UserKey.MakeMeClean();
}
}
Also, in [B], when it is closing, you can check and prompt the user if they are closing the form with unsaved changes in it, like so:
private void BForm_FormClosing(object sender, FormClosingEventArgs e)
{
//If the user is closing the form via another means than the OK button, or the Cancel button (e.g.: Top-Right-X, Alt+F4, etc).
if (this.DialogResult != DialogResult.OK && this.DialogResult != DialogResult.Ignore)
{
//check if dirty first...
if (this.UserKey.IsDirty)
{
if (MessageBox.Show("You have unsaved changes. Close and lose changes?", "Unsaved Changes", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.No)
e.Cancel = true;
}
}
}
As you can see from the examples above, this can be a very useful thing to have since it really streamlines the UI.
Caveats
Every time you implement this, you have to customize it to the object you're using. E.g.: there's no "easy" generic way of doing this without using reflection... and if you use reflection, you lose efficiency, especially in large and complex objects.
Hopefully this helps someone.
Take a look at PostSharp (http://www.postsharp.org/).
You can easily create a Attribute which marks it as dirty you can add the attrubute to each property that needs it and it keeps all your code in one place.
Roughly speaking Create an interface which has your status in make the class implement it.
Create an attribute which can be applied on properties and cast to your interface in order to set the value when something changes one of the marked properties.
Your approach is basically how I would do it. I would just
remove the setter for the Status property:
public StatusEnum Status
{
get { return _Status; }
// set { _Status = value; }
}
and instead add a function
public SetStatusClean()
{
_Status = StatusEnum.Clean;
}
As well as SetStatusDeleted() and SetStatusPurged(), because I find it better indicates the intention.
Edit
Having read the answer by Jon Skeet, I need to reconsider my approach ;-) For simple objects I would stick with my way, but if it gets more complex, his proposal would lead to much better organised code.
If your Example_Class is lightweight, consider storing the original state and then comparing the current state to the original in order to determine the changes. If not your approach is the best because stroing the original state consumes a lot of system resources in this case.
Apart from the advice of 'consider making your type immutable', here's something I wrote up (and got Jon and Marc to teach me something along the way)
public class Example_Class
{ // snip
// all properties are public get and private set
private Dictionary<string, Delegate> m_PropertySetterMap;
public Example_Class()
{
m_PropertySetterMap = new Dictionary<string, Delegate>();
InitializeSettableProperties();
}
public Example_Class(long id, string name):this()
{ this.ID = id; this.Name = name; }
private void InitializeSettableProperties()
{
AddToPropertyMap<long>("ID", value => { this.ID = value; });
AddToPropertyMap<string>("Name", value => { this.Name = value; });
}
// jump thru a hoop because it won't let me cast an anonymous method to an Action<T>/Delegate
private void AddToPropertyMap<T>(string sPropertyName, Action<T> setterAction)
{ m_PropertySetterMap.Add(sPropertyName, setterAction); }
public void SetProperty<T>(string propertyName, T value)
{
(m_PropertySetterMap[propertyName] as Action<T>).Invoke(value);
this.Status = StatusEnum.Dirty;
}
}
You get the idea.. possible improvements: Use constants for PropertyNames & check if property has really changed.
One drawback here is that
obj.SetProperty("ID", 700); // will blow up int instead of long
obj.SetProperty<long>("ID", 700); // be explicit or use 700L
Here is how i do it.
In cases where i do not need to test for specific fields being dirty,
I have an abstract class:
public abstract class SmartWrap : ISmartWrap
{
private int orig_hashcode { get; set; }
private bool _isInterimDirty;
public bool IsDirty
{
get { return !(this.orig_hashcode == this.GetClassHashCode()); }
set
{
if (value)
this.orig_hashcode = this.orig_hashcode ^ 108.GetHashCode();
else
MakeClean();
}
}
public void MakeClean()
{
this.orig_hashcode = GetClassHashCode();
this._isInterimDirty = false;
}
// must be overridden to return combined hashcodes of fields testing for
// example Field1.GetHashCode() ^ Field2.GetHashCode()
protected abstract int GetClassHashCode();
public bool IsInterimDirty
{
get { return _isInterimDirty; }
}
public void SetIterimDirtyState()
{
_isInterimDirty = this.IsDirty;
}
public void MakeCleanIfInterimClean()
{
if (!IsInterimDirty)
MakeClean();
}
/// <summary>
/// Must be overridden with whatever valid tests are needed to make sure required field values are present.
/// </summary>
public abstract bool IsValid { get; }
}
}
As well as an interface
public interface ISmartWrap
{
bool IsDirty { get; set; }
void MakeClean();
bool IsInterimDirty { get; }
void SetIterimDirtyState();
void MakeCleanIfInterimClean();
}
This allows me to do partial saves, and preserve the IsDirty state if there is other details to save. Not perfect, but covers a lot of ground.
Example of usage with interim IsDirty State (Error wrapping and validation removed for clarity):
area.SetIterimDirtyState();
if (!UpdateClaimAndStatus(area))
return false;
area.MakeCleanIfInterimClean();
return true;
This is good for most scenarios, however for some classes i want to test for each field with a backing field of original data, and either return a list of changes or at least an enum of fields changed.
With an enum of fields changed i can then push that up through a message chain for selective update of fields in remote caches.
You could also think about boxing your variables, which comes at a performance cost, but also has its merits. It is pretty consise and you cannot accidentally change a value without setting your dirty status.
public class Variable<T>
{
private T _value;
private readonly Action<T> _onValueChangedCallback;
public Variable(Action<T> onValueChangedCallback, T value = default)
{
_value = value;
_onValueChangedCallback = onValueChangedCallback;
}
public void SetValue(T value)
{
if (!EqualityComparer<T>.Default.Equals(_value, value))
{
_value = value;
_onValueChangedCallback?.Invoke(value);
}
}
public T GetValue()
{
return _value;
}
public static implicit operator T(Variable<T> variable)
{
return variable.GetValue();
}
}
and then hook in a callback that marks your class as dirty.
public class Example_Class
{
private StatusEnum _Status = StatusEnum.New;
private Variable<long> _ID;
private Variable<string> _Name;
public StatusEnum Status
{
get { return _Status; }
set { _Status = value; }
}
public long ID => _ID;
public string Name => _Name;
public Example_Class()
{
_ID = new Variable<long>(l => Status = StatusEnum.Dirty);
_Name = new Variable<string>(s => Status = StatusEnum.Dirty);
}
}
Another method is to override the GetHashCode() method to somthing like this:
public override int GetHashCode() // or call it GetChangeHash or somthing if you dont want to override the GetHashCode function...
{
var sb = new System.Text.StringBuilder();
sb.Append(_dateOfBirth);
sb.Append(_marital);
sb.Append(_gender);
sb.Append(_notes);
sb.Append(_firstName);
sb.Append(_lastName);
return sb.ToString.GetHashCode();
}
Once loaded from the database, get the hash code of the object. Then just before you save check if the current hash code is equal to the previous hash code. if they are the same, don't save.
Edit:
As people have pointed out this causes the hash code to change - as i use Guids to identify my objects, i don't mind if the hashcode changes.
Edit2:
Since people are adverse to changing the hash code, instead of overriding the GetHashCode method, just call the method something else. The point is detecting a change not whether i use guids or hashcodes for object identification.

Categories