CancelEdit fails for property with Manual Backing Field

CancelEdit fails for property with Manual Backing Field

Old forum URL: forums.lhotka.net/forums/t/11757.aspx


smumcounty posted on Tuesday, December 18, 2012

I have an Editable Root class with a property which is an Editable Child which uses a manual backing field. If I set the Child property to a valid value, call BeginEdit on the parent, null out the Child property, and then call CancelEdit on the parent, the child property is not set to the value it had before the BeginEdit call.

For example, if my parent and child objects look like this:

	public class Test : BusinessBase<Test>
	{
		private Test()
		{ }
 
		public static readonly PropertyInfo<TestChild> ChildProperty = RegisterProperty<TestChild>(c => c.Child, RelationshipTypes.PrivateField | RelationshipTypes.Child);
		private TestChild _child = null;
		public TestChild Child 
		{ 
			get { return GetProperty(ChildProperty, _child); } 
			set { SetProperty(ChildProperty, ref _child, value); } 
		}
 
		public static Test NewTest()
		{
			return DataPortal.Create<Test>();
		}
 
		protected override void DataPortal_Create()
		{
			Child = Csla.DataPortal.CreateChild<TestChild>();
		}
	}
 
	public class TestChild : BusinessBase<TestChild>
	{
		private TestChild()
		{ }
 	}

 

This test will fail because test.Child remains null:

			Test test = Test.NewTest();
			Assert.IsNotNull(test.Child);
			test.BeginEdit();
			test.Child = null;
			Assert.IsNull(test.Child);
			test.CancelEdit();
			Assert.IsNotNull(test.Child);

Am I doing something wrong or is this a limitation of manual backing fields?

If I don't use a manual backing field, then trying to read test.Child after the CancelEdit throws this InvalidCastException:

Unable to cast object of type 'System.Boolean' to type 'TestChild'.

JonnyBee replied on Wednesday, December 19, 2012

This is not a supported case.

You cannot set an object that implements IUndoableObject to null and get it restored on CancelEdit.

This is because the Undo mechanism MUST have an instance of the object to rollback the properties to original values.

When using ManagedBackingFields you will get the exception "Unable to cast object of type 'System.Boolean' to type 'TestChild'" as a result of how IUnduableObjects is handled internally in N-Level undo snapshot.

This is supported:

  [Serializable]
  public class TestChild : BusinessBase<TestChild>
  {
    public static readonly PropertyInfo<string> Prop1Property = RegisterProperty<string>(c => c.Prop1, RelationshipTypes.Child);
    public string Prop1
    {
      get { return GetProperty(Prop1Property); }
      set { SetProperty(Prop1Property, value); }
    }
 
    private TestChild()
    { }
  }
 
  [TestClass]
  public class TestTest
  {
    [TestMethod]
    public void TestEditing()
    {
      Test test = Test.NewTest();
      test.Child.Prop1 = "TEST";
      Assert.AreEqual("TEST", test.Child.Prop1);
      test.BeginEdit();
      test.Child.Prop1 = string.Empty;
      Assert.AreEqual(string.Empty, test.Child.Prop1);
      test.CancelEdit();
      Assert.AreEqual("TEST", test.Child.Prop1);
    }
  }

Copyright (c) Marimer LLC