Прекратить выполнение метода по событию - PullRequest
0 голосов
/ 27 сентября 2011

У меня есть свойство в классе, которое, если установлено, будет изменять значения некоторых других свойств, любое из которых может вызвать конкретное событие для отката (скажем, RollbackEvent). Если такое событие вызывается, то все изменения, сделанные исходным свойством, были отменены, и теперь мне нужно, чтобы это свойство остановилось на его дорожках.

Создание исключения - не вариант (я думаю), потому что будет другая сборка (и), потребляющая код (на самом деле это другая сборка, которая фиксирует второе событие в моем коде и, если она не может обработать В этом случае мой код выполняет откат, и это происходит при запуске RollbackEvent), для которого не должно создаваться никаких исключений.

Обновление

Это общая схема моего кода, и AFAIK код во второй сборке никогда не должен понимать, что исключение было выдано в первой, но после того, как «транзакция» откатывается (очевидно), успешно выполняется код на вторая сборка останавливается.

Сборка 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);
    }

}

Сборка 2

public class SomeOtherClass
{
    private SomeClass obj;

    private HandleANEvent()
    {
        obj.RollbackProcessTransaction();
        //Code in this line on never gets executed! >.<
    }
}

В принципе, все работает хорошо, когда исключение генерируется в сборке 1, оно захватывается свойством, и такое свойство затем возвращается, но код после вызова obj.RollbackProcessTransaction(); никогда не выполняется ... почему?

PS Я написал весь этот код здесь, в редакторе, потому что на самом деле я программирую на VB, так что не воспринимайте весь код там буквально, это только для вас, чтобы понять идею.

Ответы [ 2 ]

1 голос
/ 27 сентября 2011

Самый простой способ - записать значение каждого свойства перед его изменением, а затем отменить их в случае ошибки. Если каждое свойство имеет быстрый выход, если значение установлено на то же самое, это предотвратит появление новых исключений. Я немного позаимствовал из ответа Магнуса.

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
    {
    }
}
1 голос
/ 27 сентября 2011

Как это?

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;
      }
    }
}
...