Load property lazy loading - c#

I have a property which getter should load its value only the first time. The second time it returns the loaded value without loading it again:
private Object _MemberValue;
public Object MemberValue
{
get
{
if(_MemberValue == null)
{
_MemberValue = LoadMember();
}
return _MemberValue;
}
}
In VB.NET there is the Static keyword. With it you don't have to declare a class wide member.
Public Property MemberValue as Object
Get
Static value as Object = Nothing
If (value is Nothing) Then
value = LoadMember()
End If
Return value
End Get
End Property
In C# there isn't such a keyword.
Are there better C# implementations of this problem or other patterns?

Are there better C# implementations of this problem or other patterns?
Probably not. You can use Lazy<T> as an replacement if you like, but basically it is the same as your first example. Using Static in VB.NET has some serious drawbacks, so I wouldn't use it either way.
If you prefer Lazy<T>, this is what I would use:
private Lazy<object> _MemberLazy = new Lazy<object>(LoadMember);
public object MemberValue
{
get
{
return _MemberLazy.Value;
}
}

Your initial approach seems appropriate, I have never had reason to do something different. That said if your goal here is to avoid a class level field that could potentially be written to outside the getter, perhaps something like this would work. There are a number of other ReadOnly, WriteOnce, SetOnce implementations that would also work similarly.
ReadOnlyField.cs
public class ReadOnlyField<T>
{
private bool _frozen;
private T _value;
public T Value
{
get { return _value; }
set
{
if (_frozen)
throw new InvalidOperationException();
_value = value;
}
}
public void Freeze()
{
_frozen = true;
}
}
YourObject.cs
public class YourObject
{
private readonly ReadOnlyField<object> _someMember;
public object MemberValue
{
get
{
if(_someMember.Value == null)
{
_someMember.Value = LoadMember();
_someMember.Freeze();
}
return _someMember.Value;
}
}
public YourObject()
{
_someMember = new ReadOnlyField<object>();
}
}
It's not perfect. Unlike your VB.Net example; code outside of the getter could write to the field first, but at least you're protected from it being overwritten after Freeze is called.

Related

How to get Getter backing field from PropertyInfo?

I have a class as follows:
class Foo : PropertyChangedBase {
private int _property;
public int Property {
get { return _property; }
set { OnAssignPropertyChanged("Property", () => _property, value); }
}
PropertyChangedBase implements INotifyPropertyChanged with the following methods:
protected void OnAssignmentPropertyChanged<T>(string propertyName, Expression<Func<T>> fieldExpression, T value)
{
var get = fieldExpression.Compile();
if (get().Equals(value))
{
return;
}
// invoke set property method
SetProperty(fieldExpression, value);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void SetProperty<T>(Expression<Func<T>> fieldExpression, T value)
{
if (fieldExpression == null)
{
throw new ArgumentNullException(nameof(fieldExpression));
}
var memberExpression = fieldExpression.Body as MemberExpression;
if (memberExpression == null)
{
throw new ArgumentException("fieldExpression");
}
var field = memberExpression.Member as FieldInfo;
if (field == null)
{
throw new ArgumentException("fieldExpression");
}
field.SetValue(this, value);
}
I would prefer to call:
OnAssignPropertyChanged(() => Property, value);
The only way this will work is if I can get the backing field for the property getter and then pass that to SetProperty. Is it possible to get the FieldInfo or target member from the property get method?
As a general answer, yes you can do, at least under controlled conditions. But the only case you should do this is when you are absoluty sure what you are doing and only with limited support, because there will be cases you can not handle.
Have a look at the answer here: Find all property references using reflection. The target is a bit different but the approach is similar for finding field references. Since the answer there already includes the necessary code i will just outline the way to go:
All metadata items in .Net are referenced by tokens. To get tokens used inside a method you have to parse the MethodBody (by skipping all the things you wont inspect) and then resolve the found tokens in their module. Remember to use the BitConverter when reading the tokens from the stream to resolve them.
But now to the down side; the only time you can really safely use this to find the backing fields of a properties getter, is when you find a simple get method, with a well defined opcode sequence like Ldfld, Ret or something like that. Maybe you can define a few patterns that the C# compiler will emit for simple and autoimplemented properties. If you find anything different there is no other way as to resign and throw an exception, because the getter could contain any code.
Like always with reflection, only use whitelist approaches, check for the conditions you expect and throw exeptions in any other case or you will run into a NullReferenceException sooner or later.
If this is worth the trouble is for you to decide, but in general you could do this since .Net 2.0 and do not even need a fancy external lib.
No, in general case you can't. Just compare two classes:
public class Test {
private int _propA;
private int _propB;
public int PropA {get { return _propA; }}
public int PropB {get { return _propB; }}
}
public class TestSwapped {
private int _propA;
private int _propB;
// please, notice swapped backing fields
public int PropA {get { return _propB; }}
public int PropB {get { return _propA; }}
}
you'll get identical PropertyInfo[] and FieldInfo[] arrays but different backing fields
In pursuing this for a different question, here is an extension method for the simple cases - an autogenerated backing field, or a get that just returns a backing field:
public static class MethodInfoExt {
const int IL_ldarg0 = 0x02;
const int IL_ldfld = 0x7B;
public static FieldInfo FieldInfoFromGetAccessor(this MethodInfo getAccessorMI) {
var body = getAccessorMI.GetMethodBody().GetILAsByteArray();
if (body[0] == IL_ldarg0 && body[1] == IL_ldfld) {
var fieldToken = BitConverter.ToInt32(body, 2);
return getAccessorMI.DeclaringType.Module.ResolveField(fieldToken);
}
else
return default;
}
}
You can not. Property can have no backing fields or sets of backing fields.
Even set property can have no backing fields at all.
public Int32 Prop
{
set { Debug.WriteLine(value.ToString()); }
get { return 1; }
}
What are you expecting to get in FieldInfo?
Property is just a syntax sugar for a pair of set/get methods, or mutators. Being a method allows them to contain as much code as needed, including being just empty and, of course, there is no requirement to have a backing field from compiler perspective.

Container for properties values

When .NET 4.5 was released i started using such great Attribute as CallerMemberName. It's easier to understand code, developers can write it faster also. It's like a snippet, not only a feature for debug/test purposes.
So I have a question. Is it normal to create and use something like this?
public class PropertyStore
{
Dictionary<string, object> data = new Dictionary<string,object>();
ViewModelBase modelBase;
internal PropertyStore(ViewModelBase _base)
{
modelBase = _base;
}
public void SetValue<T>(T value = default(T), [CallerMemberName] string prop = "")
{
T prev = GetValue<T>(prop);
if ((prev == null && value == null) || (prev != null && prev.Equals(value))) return;
data[prop] = value;
modelBase.OnPropertyChanged(prop);
}
public T GetValue<T>([CallerMemberName] string prop = "")
{
if (!data.ContainsKey(prop))
data[prop] = default(T);
return (T)data[prop];
}
}
Class-helper, that makes other class more readable, and also we have list of our properties without need to use Reflection.
The usage is:
public class SampleClass : ViewModelBase
{
PropertyStore PropertyStore;
public SampleClass ()
{
PropertyStore = new PropertyStore(this);
}
public string Key
{
get { return PropertyStore.GetValue<string>(); }
set { PropertyStore.SetValue(value); }
}
public DateTime Date
{
get { return PropertyStore.GetValue<DateTime>(); }
set { PropertyStore.SetValue(value); }
}
public bool IsSelected
{
get { return PropertyStore.GetValue<bool>(); }
set { PropertyStore.SetValue(value); }
}
}
The class ViewModelBase here simply implements INotifyPropertyChanged interface.
As I understand, this approach is something like Microsoft Dependency Properties, but I don't need all power of DependencyObject class, and I don't want inherit it.
With something like this I can use Binding, because it's enough to implement INotifyPropertyChanged, also we have no fields (as for me, i try to use properties smarter, than using fields directly (however, there is no problem to use Dictionary directly ^_^))
Sorry for my bad English... Not main language and not much practice.
Another Sample (after moving Methods to base class)
public class SampleClass : ViewModelBase
{
public string Key
{
get { return GetValue<string>(); }
set { SetValue(value); }
}
public DateTime Date
{
get { return GetValue<DateTime>(); }
set { SetValue(value); }
}
public bool IsSelected
{
get { return GetValue<bool>(); }
set { SetValue(value); }
}
}
No diff with Microsoft's WPF Property System.
Only feature you'll get with it is an ability to access property values via Dictionary.Get|Set methods.
You can get this ability with field based implementation of INotifyPropertyChanged. You can access property values by its name using dictionary, with property name to precompiled delegate mapping like it done in Yappi project.
var dateValue= Property<SampleClass>.Get<DateTime>(this,"Date");
Property<SampleClass>.Set<DateTime>(this,"Date",DateTime.Now);
Both can be rewritten as extension methods.
Nice idea, property bag without reflection and it will even work with obfuscation.
I don't see major problems with it but you may consider the following:
The prop parameter is optional so potentially a bug can be introduced by given a value in the call.
Value types will get boxed.
Access to the fields is relatively more expensive, can be a factor more expensive as you have much more code in a simple get (especially with boxing).
Dictionary takes more space than the number of properties you keep in (especially with boxing).
Each property also stores a string of the property name adding to the overhead.

How to handle unassigned properties when using Singleton Pattern

I have created the following class based on a Singleton Pattern:
public sealed class UTrans
{
private static volatile UTrans _instance;
private static readonly object syncRoot = new Object();
private UTrans(){}
private static UTrans Instance
{
get
{
if (_instance == null)
{
lock (syncRoot)
{
if (_instance == null)
_instance = new UTrans();
}
}
return _instance;
}
}
}
Within this Class I have created an enum property and string property
private static MethodType _method; // Alphabectic 1 - 50
public static MethodType Method
{
get { return _method; }
set { _method = value; }
}
private static string _uName;
public static string UserName
{
get { return _uName; }
set { _uName = value; }
}
I also have some methods that take a number of arguments in this class. When I call the class instance in code, if the user assigns values to the properties; those values will be used. Otherwise, the values passed as arguments will be used.
This works fine in the case of the UserName property by checking for a null value on the property:
var un = UserName ?? user;
However I cannot perform the same check for the enumeration property because it seems that the property automatically assumes the 1st value of the enumeration if one is not assigned.
I tried to circumvent the issue by assigning the 1st value of the enum as "Unspecified". Then I may proceed to code as such:
var processMethod = TranslateMethodType(Method) == "Unspecified" ? method : Method;
Where TranslateMethodType is a private method that converts the selected enumeration to a equivalent string value.
I don't believe this is the most elegant approach to the issue though and would like some feedback on possible alternatives to this issue.
Is there a way to check that a value has not been set for the MethodType property by the user of the class without having to add an "Unspecified" value as the first value since this value is ONLY there as a way to indicate no value was set?
Obviously, this may not be the case if the user decides to use the value and it would yield undesirable results to construct the code this way.
Can a enumeration Method be marked as nullable???
Can a enumeration Method be marked as nullable???
Yes.
public Nullable<MyEnum> Bob(){
//stuff
}
var bob = Bob() ?? MyEnum.Default;
Yes, you can make the Method field/property nullable.
private static MethodType? _method; // Alphabectic 1 - 50
public static MethodType? Method
{
get { return _method; }
set { _method = value; }
}
Then you can do
var processMethod = Method == null ? method : Method.Value;
or
var processMethod = Method.HasValue ? Method.Value: method;
You can mark it as nullable however what you're experiencing is expected behaviour.
Value types that are members of a reference type are initialized to 0. This is why you should always provide a value of 0 for your enums. If you don't, then users of your class will never know that the class has invalid state.

C# stop property change at runtime

I have been trying to build a user control with some custom properties set in the designer. However the control involves some interop code and settings which shouldn't be adjusted at runtime. Is there a way to stop the values being changed after they have been initially set by the designer code?
Are you able to modify the property definition? One approach is, add a sentinel to the property setter, and allow only one set operation (which would usually be done by InitializeComponent()):
private int _myProperty;
private bool _isMyPropertySet = false;
public int MyProperty
{
set
{
if (!_isMyPropertySet)
{
_isMyPropertySet = true;
_myProperty = value;
}
else
{
throw new NotSupportedException();
}
}
}
Michael provided a great answer, and it will solve your problem at runtime. However, at design time, if you need to be able to change that value more than once (it is design time, and the probability is likely high), then you will want to combine the DesignMode check with Michaels example:
private int _myProperty;
private bool _isMyPropertySet = false;
public int MyProperty
{
set
{
if (this.DesignMode || !_isMyPropertySet)
{
_isMyPropertySet = true;
_myProperty = value;
}
else
{
throw new NotSupportedException();
}
}
}
Now you will be able to edit this value to your hearts content during design, without running into that NotSupportedException() and getting a botched designer on the second set.
You could throw an exception inside the property setter?
public int SomeProperty {
set {
if(designerComplete) {
throw new IllegalOperationException();
}
}
}
Set designerComplete as a class variable - set it to true after the InitializeComponent method is called in the constructor.
The WinForms architecture provides a built-in way to test whether code is currently being executed in design mode - the Component.DesignMode property.
So you probably want an implementation something like this:
private int _foo;
public int Foo
{
get { return _foo; }
set
{
if (this.DesignMode)
throw new InvalidOperationException();
_foo = value;
}
}

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