File: System\Activities\Runtime\FaultCallbackWrapper.cs
Project: ndp\cdf\src\NetFx40\System.Activities\System.Activities.csproj (System.Activities)
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
 
namespace System.Activities.Runtime
{
    using System;
    using System.Runtime;
    using System.Runtime.Serialization;
    using System.Security;
 
    [DataContract]
    class FaultCallbackWrapper : CallbackWrapper
    {
        static readonly Type faultCallbackType = typeof(FaultCallback);
        static readonly Type[] faultCallbackParameters = new Type[] { typeof(NativeActivityFaultContext), typeof(Exception), typeof(ActivityInstance) };
 
        public FaultCallbackWrapper(FaultCallback callback, ActivityInstance owningInstance)
            : base(callback, owningInstance)
        {
        }
 
        [Fx.Tag.SecurityNote(Critical = "Because we are calling EnsureCallback",
            Safe = "Safe because the method needs to be part of an Activity and we are casting to the callback type and it has a very specific signature. The author of the callback is buying into being invoked from PT.")]
        [SecuritySafeCritical]
        public void Invoke(NativeActivityFaultContext faultContext, Exception propagatedException, ActivityInstance propagatedFrom)
        {
            EnsureCallback(faultCallbackType, faultCallbackParameters);
            FaultCallback faultCallback = (FaultCallback)this.Callback;
            faultCallback(faultContext, propagatedException, propagatedFrom);
        }
 
        public WorkItem CreateWorkItem(Exception propagatedException, ActivityInstance propagatedFrom, ActivityInstanceReference originalExceptionSource)
        {
            return new FaultWorkItem(this, propagatedException, propagatedFrom, originalExceptionSource);
        }
 
        [DataContract]
        internal class FaultWorkItem : ActivityExecutionWorkItem
        {
            FaultCallbackWrapper callbackWrapper;
            Exception propagatedException;
            ActivityInstance propagatedFrom;
            ActivityInstanceReference originalExceptionSource;
 
            public FaultWorkItem(FaultCallbackWrapper callbackWrapper, Exception propagatedException, ActivityInstance propagatedFrom, ActivityInstanceReference originalExceptionSource)
                : base(callbackWrapper.ActivityInstance)
            {
                this.callbackWrapper = callbackWrapper;
                this.propagatedException = propagatedException;
                this.propagatedFrom = propagatedFrom;
                this.originalExceptionSource = originalExceptionSource;
            }
 
            public override ActivityInstance OriginalExceptionSource
            {
                get
                {
                    return this.originalExceptionSource.ActivityInstance;
                }
            }
 
            [DataMember(Name = "callbackWrapper")]
            internal FaultCallbackWrapper SerializedCallbackWrapper
            {
                get { return this.callbackWrapper; }
                set { this.callbackWrapper = value; }
            }
 
            [DataMember(Name = "propagatedException")]
            internal Exception SerializedPropagatedException
            {
                get { return this.propagatedException; }
                set { this.propagatedException = value; }
            }
 
            [DataMember(Name = "propagatedFrom")]
            internal ActivityInstance SerializedPropagatedFrom
            {
                get { return this.propagatedFrom; }
                set { this.propagatedFrom = value; }
            }
 
            [DataMember(Name = "originalExceptionSource")]
            internal ActivityInstanceReference SerializedOriginalExceptionSource
            {
                get { return this.originalExceptionSource; }
                set { this.originalExceptionSource = value; }
            }
 
            public override void TraceCompleted()
            {
                if (TD.CompleteFaultWorkItemIsEnabled())
                {
                    TD.CompleteFaultWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id, this.originalExceptionSource.ActivityInstance.Activity.GetType().ToString(), this.originalExceptionSource.ActivityInstance.Activity.DisplayName, this.originalExceptionSource.ActivityInstance.Id, this.propagatedException);
                }
            }
 
            public override void TraceScheduled()
            {
                if (TD.ScheduleFaultWorkItemIsEnabled())
                {
                    TD.ScheduleFaultWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id, this.originalExceptionSource.ActivityInstance.Activity.GetType().ToString(), this.originalExceptionSource.ActivityInstance.Activity.DisplayName, this.originalExceptionSource.ActivityInstance.Id, this.propagatedException);
                }
            }
 
            public override void TraceStarting()
            {
                if (TD.StartFaultWorkItemIsEnabled())
                {
                    TD.StartFaultWorkItem(this.ActivityInstance.Activity.GetType().ToString(), this.ActivityInstance.Activity.DisplayName, this.ActivityInstance.Id, this.originalExceptionSource.ActivityInstance.Activity.GetType().ToString(), this.originalExceptionSource.ActivityInstance.Activity.DisplayName, this.originalExceptionSource.ActivityInstance.Id, this.propagatedException);
                }
            }
 
            public override bool Execute(ActivityExecutor executor, BookmarkManager bookmarkManager)
            {
                NativeActivityFaultContext faultContext = null;
 
                try
                {
                    faultContext = new NativeActivityFaultContext(this.ActivityInstance, executor, bookmarkManager, this.propagatedException, this.originalExceptionSource);
                    this.callbackWrapper.Invoke(faultContext, this.propagatedException, this.propagatedFrom);
 
                    if (!faultContext.IsFaultHandled)
                    {
                        SetExceptionToPropagateWithoutAbort(this.propagatedException);
                    }
                }
                catch (Exception e)
                {
                    if (Fx.IsFatal(e))
                    {
                        throw;
                    }
 
                    this.ExceptionToPropagate = e;
                }
                finally
                {
                    if (faultContext != null)
                    {
                        faultContext.Dispose();
                    }
 
                    // Tell the executor to decrement its no persist count persistence of exceptions is disabled.
                    executor.ExitNoPersistForExceptionPropagation();
                }
 
                return true;
            }
        }
    }
}