I need to know how do you check if an object is changed. Basically I need something like a property that is named TrackChanges, when I set it true once and if any data within this object is "changed", a method on the same object (IsObjectChanged) can return true.
Did you ever needed such a thing and how did you solve it? I do not want to invent the wheel if there is already a best-practice for such scenario?
I was thinking to clone the object before I call TrackChange=true, in its setter. And when I call IsObjectChanged() By using reflection I will compare all the public field values of it with the cloned copy. I am not sure if it is a good way.
Any advices?
thanks, burak ozdogan
When I need to track changes to properties on my objects for testing I hook an event handler on the objects PropertyChanged event. Will that help you? Then your tests can do whatever action they want based on the change. Normally I count the number of changes, and add the changes to dictionaries, etc.
To achieve this your class must implement the INotifyPropertyChanged interface. Then anyone can attach and listen to changed properties:
public class MyClass : INotifyPropertyChanged { ... } [TestFixture] public class MyTestClass { private readonly Dictionary<string, int> _propertiesChanged = new Dictionary<string, int>(); private int _eventCounter; [Test] public void SomeTest() { // First attach to the object var myObj = new MyClass(); myObj.PropertyChanged += SomeCustomEventHandler; myObj.DoSomething(); // And here you can check whether the object updated properties - and which - // dependent on what you do in SomeCustomEventHandler. // E.g. that there are 2 changes - properties Id and Name changed once each: Assert.AreEqual(2, _eventCounter); Assert.AreEqual(1, _propertiesChanged["Id"]); Assert.AreEqual(1, _propertiesChanged["Name"]); } // In this example - counting total number of changes - and count pr property. // Do whatever suits you. private void SomeCustomEventHandler(object sender, System.ComponentModel.PropertyChangedEventArgs e) { var property = e.PropertyName; if (_propertiesChanged.ContainsKey(property)) _propertiesChanged[property]++; else _propertiesChanged[property] = 1; _eventCounter++; } }
There are two parts to this. Events for change notification are one piece, but maintaining history is another important piece. Entity Framework does this too (as does LINQ to SQL), and I've implemented this in my own code as well. At minimum, you keep a flag for a member to say that it has changed. Depending on your requirements, you may keep the original value as well. This usually becomes the task of a separate object. Entity Framework keeps its change tracking in a separate object (EntityState, if I remember correctly).
In my own code, I developed a "DataMember" class that not only held the values, but also kept change flag, null status, and various other useful things. These DataMembers were private members in an Entity class, and the Entity provided properties that exposed the data as simple data types. The property get and set methods interacted with the DataMember to "do the right thing", but the DataMember did change tracking. My Entity class inherited from an "EntityBase" class that provided methods to check for change at the entity level, accept changes (reset change flags), etc. Adding change notification will be the next thing I do, but having a DataMember class for individual data elements, and an EntityBase to own the change notification event handler, will simplify this a lot.
EDITED TO ADD:
Now that I'm at work, I can add some code samples. Here's the interface definition for my DataMember class:
public interface IDataMember<T> : IDataMember { T Value { get; set; } T Get(); void Set(T value); } public interface IDataMember { string FieldName { get; set; } string OracleName { get; set; } Type MemberType { get; } bool HasValue { get; set; } bool Changed { get; set; } bool NotNull { get; set; } bool PrimaryKey { get; set; } bool AutoIdentity { get; set; } EntityBase Entity { get; set;} object GetObjectValue(); void SetNull(); }
Here's a typical property in an entity class:
private DataMember<bool> m_Monday; public bool? Monday { get { if (m_Monday.HasValue) return m_Monday.Get(); else return null; } set { if (value.HasValue) m_Monday.Set(value.Value); else m_Monday.SetNull(); } }
Note that the DataMember can support properties as nullable, or not.
Constructor code to add a DataMember:
m_Monday = new DataMember<bool>("Monday"); Members.Add(m_Monday);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With