Stop Executing Method on Event
I have a property in a class that, when set, it will change some other properties's values, any of which may raise an specific event for rollback (say RollbackEvent
). If such event is fired then all changes made by the original property have been rolled back and now I need that property to stop on its tracks.
Throwing an exception is not an option (I think) 'cause there'll be another assembly(s) consuming the code (actually is the other assembly who captures a second event in my code and, if it fails to handle the situation, it commands my code to rollback and that's when the RollbackEvent is fired) for which no exception should be thrown.
Update
This is a general outline of my code, and AFAIK the code in the second Assembly should never realize an exception was thrown in the first one, but the after the "transactio开发者_运维问答n" is rolled back (apparently) successfully the code on the second assembly stops executing.
Assembly 1
public class Someclass
{
public String SomeField
{
get { return this._someField; }
set
{
try
{
this.BackupSomeFields();
this._someField = value;
//Some other Properties are changed
//One of which may (and will for the purposes of the question) throw a DocumentRolledbackException exception
}
catch (DocumentRolledbackException ex)
{
return;
}
}
}
public String SomeOtherField
{
get { return this._someOtherField; }
set
{
this._someOtherField = value;
//Raise AN event (handled in Assembly 2)
}
}
public void RollbackProcessTransaction()
{
//Rollback changes with the backup created by the SomeField property
//Raise THE event
DocumentRolledBack(this, new EventArgs());
}
private void MyBase_DocumentRolledBack(Object sender, EventArgs e)
{
//This method is called when the DocumentRolledBack event is fired in the RollbackProcessTransaction method.
throw new DocumentRolledbackException(this);
}
}
Assembly 2
public class SomeOtherClass
{
private SomeClass obj;
private HandleANEvent()
{
obj.RollbackProcessTransaction();
//Code in this line on never gets executed! >.<
}
}
Basically it's all working good, when the exception is thrown in assembly 1 it gets captured by the property and such property then returns, but the code after the invocation of obj.RollbackProcessTransaction();
never gets executed... why?
P.S. I wrote all that code here in the editor 'cause I actually program in VB, so don't take all the code there so literally, that's just for you to get the idea.
Like this?
public class Test
{
public object Foo1
{
try
{
Foo2 = 1;
Foo3 = 2;
Foo4 = 3;
}
catch (RollbackException ex) { }
}
private void DoRollback()
{
throw new RollbackException();
}
public object Foo2 { get; set; }
public object Foo3 { get; set; }
public object Foo4 { get; set; }
private class RollbackException : Exception
{
}
}
EDIT:
public class SomeOtherClass
{
private SomeClass obj;
public SomeOtherClass()
{
var backup = obj.Clone();
try
{
obj.SomeField = "test";
}
catch (RollbackException ex)
{
obj = backup;
}
}
}
The simplest way would be to record each property's value before changing it, then revert them in the event of an error. If each property has a quick exit if the value is set the same, it'll prevent further exceptions being thrown. I'm borrowing a little from Magnus' answer.
public class Test
{
public object Foo1
{
object oldfoo2 = Foo2;
object oldfoo3 = Foo3;
object oldfoo4 = Foo4;
try
{
Foo2 = 1;
Foo3 = 2;
Foo4 = 3;
}
catch (RollbackException ex) {
Foo4 = oldfoo4;
Foo3 = oldfoo3;
Foo2 = oldfoo2;
}
}
public object Foo2 {
get {
return foo2;
}
set {
if (value == foo2) return;
if (isInvalid(value)) throw new RollbackException();
foo2 = value;
}
}
private object foo2 = null;
public object Foo3 { /* As Foo2 */ }
public object Foo4 { /* As Foo2 */ }
private class RollbackException : Exception
{
}
}
精彩评论