User: mzywitza
Date: 2010/01/13 10:58 AM

Added:
 /ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/
  ConversationCanceledEventArgs.cs

Modified:
 /ActiveRecord/trunk/src/Castle.ActiveRecord.Tests/Conversation/
  ConversationScenarioTest.cs, ScopedConversationTests.cs
 /ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/
  IConversation.cs, ScopedConversation.cs

Log:
 Finished IConversation.

File Changes:

Directory: /ActiveRecord/trunk/src/Castle.ActiveRecord.Tests/Conversation/
==========================================================================

File [modified]: ConversationScenarioTest.cs
Delta lines: +75 -5
===================================================================

--- 
ActiveRecord/trunk/src/Castle.ActiveRecord.Tests/Conversation/ScopedConversationTests.cs
    2010-01-13 11:03:51 UTC (rev 6657)
+++ 
ActiveRecord/trunk/src/Castle.ActiveRecord.Tests/Conversation/ScopedConversationTests.cs
    2010-01-13 17:58:00 UTC (rev 6658)
@@ -117,9 +117,9 @@
                {
                        using (var c = new ScopedConversation())
                        {
-                               Assert.That(c.Canceled, Is.False);
+                               Assert.That(c.IsCanceled, Is.False);
                                c.Cancel();
-                               Assert.That(c.Canceled);
+                               Assert.That(c.IsCanceled);
                        }
                }
 
@@ -128,15 +128,85 @@
                {
                        using (var c = new ScopedConversation())
                        {
-                               Assert.That(c.Canceled, Is.False);
+                               Assert.That(c.IsCanceled, Is.False);
                                c.Cancel();
-                               Assert.That(c.Canceled);
+                               Assert.That(c.IsCanceled);
                                c.Restart();
-                               Assert.That(c.Canceled, Is.False);
+                               Assert.That(c.IsCanceled, Is.False);
                        }
                }
 
+               [Test]
+               public void ConversationIsCanceledAfterErrorInExecute()
+               {
+                       using (var c = new ScopedConversation())
+                       {
+                               Assert.Throws<ApplicationException>(() => 
c.Execute(() => new PostLazy().SaveWithException()));
+                               Assert.That(c.IsCanceled);
+                       }
+               }
 
+               [Test]
+               public void ConversationIsCanceledAfterSilentError()
+               {
+                       using (var c = new ScopedConversation())
+                       {
+                               c.ExecuteSilently(() => new 
PostLazy().SaveWithException());
+                               Assert.That(c.IsCanceled);
+                       }
+               }
 
+               [Test]
+               public void TriggersEventWhenCanceling()
+               {
+
+                       bool triggered = false;
+                       using (var c = new ScopedConversation())
+                       {
+                               c.Canceled += (conv,args) => triggered = true;
+                               c.Cancel();
+                       }
+
+                       Assert.That(triggered);
+               }
+
+               [Test]
+               public void TriggersWithRightArgsWhenCanceling()
+               {
+
+                       bool triggered = false;
+                       bool userCancel = false;
+                       using (var c = new ScopedConversation())
+                       {
+                               c.Canceled += (conv, args) => { triggered = 
true;
+                                                               userCancel = 
args.CanceledByUser; };
+                               c.Cancel();
+                       }
+
+                       Assert.That(triggered);
+                       Assert.That(userCancel);
+               }
+
+               [Test]
+               public void TriggersWithRightArgsWhenCancelingAfterException()
+               {
+
+                       bool triggered = false;
+                       Exception ex = null;
+                       using (var c = new ScopedConversation())
+                       {
+                               c.Canceled += (conv, args) =>
+                               {
+                                       triggered = true;
+                                       ex = args.Exception;
+                               };
+                               c.ExecuteSilently(()=>new 
PostLazy().SaveWithException());
+                       }
+
+                       Assert.That(triggered);
+                       Assert.That(ex, Is.Not.Null
+                               .And.InstanceOf<ApplicationException>());
+               }
+
        }
 }

File [modified]: ScopedConversationTests.cs
Delta lines: +0 -0
===================================================================

Directory: /ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/
========================================================================

File [added]: ConversationCanceledEventArgs.cs
Delta lines: +30 -1
===================================================================

--- 
ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/IConversation.cs    
    2010-01-13 11:03:51 UTC (rev 6657)
+++ 
ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/IConversation.cs    
    2010-01-13 17:58:00 UTC (rev 6658)
@@ -80,6 +80,35 @@
                /// <summary>
                /// Whether the conversation is canceled
                /// </summary>
-               bool Canceled { get; }
+               bool IsCanceled { get; }
+
+               /// <summary>
+               /// Executes a block of code in the context of the
+               /// conversation. This allows to use ActiveRecord
+               /// without any scopes by doing all persistence calls
+               /// within Execute.
+               /// If an exception is caught, the conversation is
+               /// automatically canceled and the exception handed
+               /// down to the calling code. 
+               /// </summary>
+               /// <param name="action">The code to execute</param>
+               /// <remarks>
+               /// This allows to use the interface directly, for example
+               /// if it is served through an IoC-Container.
+               /// </remarks>
+               void Execute(Action action);
+
+               /// <summary>
+               /// Executes a block of code. The conversation is canceled
+               /// if an exception occurs, but the exception will not be
+               /// handed to the calling code.
+               /// </summary>
+               /// <param name="action">The code to execute</param>
+               void ExecuteSilently(Action action);
+
+               /// <summary>
+               /// Fired when the conversation is canceled.
+               /// </summary>
+               event EventHandler<ConversationCanceledEventArgs> Canceled;
     }
 }

File [modified]: IConversation.cs
Delta lines: +58 -8
===================================================================

--- 
ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/ScopedConversation.cs
   2010-01-13 11:03:51 UTC (rev 6657)
+++ 
ActiveRecord/trunk/src/Castle.ActiveRecord/Framework/Scopes/ScopedConversation.cs
   2010-01-13 17:58:00 UTC (rev 6658)
@@ -45,7 +45,7 @@
 
                private ConversationFlushMode flushMode;
 
-               private bool canceled = false;
+               private bool _isCanceled = false;
                private Dictionary<ISessionFactory, ISession> openedSessions = 
new Dictionary<ISessionFactory,ISession>();
 
                /// <inheritDoc />
@@ -58,7 +58,7 @@
                {
                        foreach (var session in openedSessions.Values)
                        {
-                               if (canceled)
+                               if (_isCanceled)
                                        session.Transaction.Rollback();
                                else
                                {
@@ -75,9 +75,16 @@
                /// <inheritDoc />
                public void Cancel()
                {
-                       canceled = true;
+                       DoCancel(true, null);
                }
 
+               private void DoCancel(bool userCanceled, Exception 
exceptionCaught)
+               {
+                       _isCanceled = true;
+                       var args = new 
ConversationCanceledEventArgs(userCanceled, exceptionCaught);
+                       TriggerCanceled(args);
+               }
+
                /// <inheritDoc />
                public void Flush()
                {
@@ -92,7 +99,7 @@
                public void Restart()
                {
                        ClearSessions();
-                       canceled = false;
+                       _isCanceled = false;
                }
 
                /// <inheritDoc />
@@ -113,11 +120,33 @@
                }
 
                /// <inheritDoc />
-               public bool Canceled
+               public bool IsCanceled
                {
-                       get { return canceled; }
+                       get { return _isCanceled; }
                }
 
+               /// <summary>
+               /// Executes the action.
+               /// </summary>
+               /// <param name="action">The action</param>
+               /// <param name="silently">Whether to throw on exception</param>
+               public void Execute(Action action, bool silently)
+               {
+                       try
+                       {
+                               using (new ConversationalScope(this))
+                               {
+                                       action();
+                               }
+                       }
+                       catch (Exception ex)
+                       {
+                               DoCancel(false, ex);
+                               if (!silently) 
+                                       throw;
+                       }
+               }
+
                /// <inheritDoc />
                public ISession GetSession(ISessionFactory factory, 
IInterceptor interceptor)
                {
@@ -129,11 +158,11 @@
 
                private void AssertNotCanceled()
                {
-                       if (canceled)
+                       if (_isCanceled)
                        {
                                throw new ActiveRecordException(
                                        "A session was requested from a 
conversation that has "+
-                                       "been already canceled. Please check 
that after the "+
+                                       "been already _isCanceled. Please check 
that after the "+
                                        "cancellation of a conversation no more 
"+
                                        "ConversationalScopes are opened using 
it.");
                        }
@@ -149,5 +178,26 @@
                                NHibernate.FlushMode.Never;
                        openedSessions.Add(factory,session);
                }
+
+               /// <inheritDoc />
+               public void Execute(Action action)
+               {
+                       Execute(action,false);
+               }
+
+               /// <inheritDoc />
+               public void ExecuteSilently(Action action)
+               {
+                       Execute(action, true);
+               }
+
+               /// <inheritDoc />
+               public event EventHandler<ConversationCanceledEventArgs> 
Canceled;
+
+               private void TriggerCanceled(ConversationCanceledEventArgs args)
+               {
+                       if (Canceled != null)
+                               Canceled(this, args);
+               }
        }
 }

File [modified]: ScopedConversation.cs
Delta lines: +26 -0
===================================================================

--- 
ActiveRecord/trunk/src/Castle.ActiveRecord.Tests/Conversation/ConversationScenarioTest.cs
   2010-01-13 11:03:51 UTC (rev 6657)
+++ 
ActiveRecord/trunk/src/Castle.ActiveRecord.Tests/Conversation/ConversationScenarioTest.cs
   2010-01-13 17:58:00 UTC (rev 6658)
@@ -165,7 +165,33 @@
                }
        }
 
+       [Test]
+       public void CanUseIConversationDirectly()
+       {
+               ArrangeRecords();
 
+               using (IConversation conversation = new ScopedConversation())
+               {
+                       BlogLazy blog = null;
+                       conversation.Execute(() => { blog = 
BlogLazy.FindAll().First(); });
+
+                               Assert.That(blog, Is.Not.Null);
+                               Assume.That(blog.Author, Is.EqualTo("Markus"));
+
+                               // Lazy access
+                               Assert.That(blog.PublishedPosts.Count, 
Is.EqualTo(1));
+
+                       blog.Author = "Anonymous";
+
+                       conversation.Execute(() => blog.Save());
+                               
+               }
+
+                       Assert.That(BlogLazy.FindAll().First().Author, 
Is.EqualTo("Anonymous"));
+       }
+
+
+
        private void ArrangeRecords()
        {

-- 
You received this message because you are subscribed to the Google Groups 
"Castle Project Commits" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/castle-project-commits?hl=en.


Reply via email to