Skip to content
Igor Tkachev edited this page May 20, 2016 · 1 revision

Home / Aspects

This aspect simplifies asynchronous operations. Note the AsyncAspect is not compatible with other type builders that generate a method body. If you apply them along with the AsyncAspect to an abstract method, they will be igored.

AsyncAspect.cs

using System;
using System.Threading;

using NUnit.Framework;

using BLToolkit.Aspects;
using BLToolkit.Reflection;

namespace HowTo.Aspects
{
    public abstract class AsyncTestObject
    {
        // This is a member we will call asynchronously.
        //
        public int Test(int intVal, string strVal)
        {
            Thread.Sleep(200);
            return intVal;
        }

        // Begin async method should take the same parameter list as the Test method and return IAsyncResult.
        // Two additional parameters can be provided: AsyncCallback and state object.
        // 'Begin' prefix is a part of the default naming convention.
        //
        [Async] public abstract IAsyncResult BeginTest(int intVal, string strVal);
        [Async] public abstract IAsyncResult BeginTest(int intVal, string strVal, AsyncCallback callback);
        [Async] public abstract IAsyncResult BeginTest(int intVal, string strVal, AsyncCallback callback, object state);

        // End async method should take IAsyncResult and return the same type as the Test method.
        // 'End' prefix is a part of the default naming convention.
        //
        [Async] public abstract int          EndTest  (IAsyncResult asyncResult);

        // Begin/End naming convention is not required. You can use any name 
        // if you provide the target method name as a parameter of the Async attribute.
        //
        [Async("Test")]
        public abstract IAsyncResult AnyName(int intVal, string strVal, AsyncCallback callback, object state);

        // Here we provide the parameter list along with the method name.
        //
        [Async("Test", typeof(int), typeof(string))]
        public abstract int         AnyName(IAsyncResult asyncResult);
    }

    [TestFixture]
    public class AsyncAspectTest
    {
        [Test]
        public void AsyncTest()
        {
            AsyncTestObject o = TypeAccessor<AsyncTestObject>.CreateInstance();

            IAsyncResult ar = o.BeginTest(1, "10");
            Assert.AreEqual(1, o.EndTest(ar));
        }

        private static void CallBack(IAsyncResult ar)
        {
            Console.WriteLine("Callback");

            AsyncTestObject o = (AsyncTestObject)ar.AsyncState;
            o.EndTest(ar);
        }

        [Test]
        public void CallbackTest()
        {
            AsyncTestObject o = TypeAccessor<AsyncTestObject>.CreateInstance();

            o.BeginTest(2, null, CallBack, o);
        }

        [Test]
        public void AnyNameTest()
        {
            AsyncTestObject o = TypeAccessor<AsyncTestObject>.CreateInstance();

            IAsyncResult ar = o.AnyName(2, null, null, null);
            Assert.AreEqual(2, o.AnyName(ar));
        }
    }
}

BLToolkit type builder will generate the following for the class above:

[BLToolkitGenerated]
internal delegate int TestObject$Test$Delegate(int, string);

[BLToolkitGenerated]
public sealed class AsyncTestObject : HowTo.Aspects.AsyncAspectTest.AsyncTestObject
{
    public override IAsyncResult BeginTest(int intVal, string strVal)
    {
        AsyncAspectBuilder.InternalAsyncResult r = new AsyncAspectBuilder.InternalAsyncResult();

        r.Delegate    = new TestObject$Test$Delegate(base.Test);
        r.InnerResult = r.Delegate.BeginInvoke(intVal, strVal, null, null);

        return r;
    }

    public override IAsyncResult BeginTest(int intVal, string strVal, AsyncCallback callback)
    {
        AsyncAspectBuilder.InternalAsyncResult r = new AsyncAspectBuilder.InternalAsyncResult();

        r.Delegate      = new TestObject$Test$Delegate(base.Test);
        r.AsyncCallback = callback;
        r.InnerResult   = r.Delegate.BeginInvoke(intVal, strVal, new AsyncCallback(r.CallBack), null);

        return r;
    }

    public override IAsyncResult BeginTest(int intVal, string strVal, AsyncCallback callback, object state)
    {
        AsyncAspectBuilder.InternalAsyncResult r = new AsyncAspectBuilder.InternalAsyncResult();

        r.Delegate      = new TestObject$Test$Delegate(base.Test);
        r.AsyncCallback = callback;
        r.InnerResult   = r.Delegate.BeginInvoke(intVal, strVal, new AsyncCallback(r.CallBack), state);

        return r;
    }

    public override int EndTest(IAsyncResult asyncResult)
    {
        AsyncAspectBuilder.InternalAsyncResult r = (AsyncAspectBuilder.InternalAsyncResult)asyncResult;

        return ((TestObject$Test$Delegate)r.Delegate).EndInvoke(r.InnerResult);
    }
}
Clone this wiki locally