Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/aspnetwebstack.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Web.Mvc/Async/ReflectedAsyncActionDescriptor.cs')
-rw-r--r--src/System.Web.Mvc/Async/ReflectedAsyncActionDescriptor.cs188
1 files changed, 188 insertions, 0 deletions
diff --git a/src/System.Web.Mvc/Async/ReflectedAsyncActionDescriptor.cs b/src/System.Web.Mvc/Async/ReflectedAsyncActionDescriptor.cs
new file mode 100644
index 00000000..b1380e84
--- /dev/null
+++ b/src/System.Web.Mvc/Async/ReflectedAsyncActionDescriptor.cs
@@ -0,0 +1,188 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Threading;
+
+namespace System.Web.Mvc.Async
+{
+ public class ReflectedAsyncActionDescriptor : AsyncActionDescriptor
+ {
+ private readonly object _executeTag = new object();
+
+ private readonly string _actionName;
+ private readonly ControllerDescriptor _controllerDescriptor;
+ private readonly Lazy<string> _uniqueId;
+ private ParameterDescriptor[] _parametersCache;
+
+ public ReflectedAsyncActionDescriptor(MethodInfo asyncMethodInfo, MethodInfo completedMethodInfo, string actionName, ControllerDescriptor controllerDescriptor)
+ : this(asyncMethodInfo, completedMethodInfo, actionName, controllerDescriptor, true /* validateMethods */)
+ {
+ }
+
+ internal ReflectedAsyncActionDescriptor(MethodInfo asyncMethodInfo, MethodInfo completedMethodInfo, string actionName, ControllerDescriptor controllerDescriptor, bool validateMethods)
+ {
+ if (asyncMethodInfo == null)
+ {
+ throw new ArgumentNullException("asyncMethodInfo");
+ }
+ if (completedMethodInfo == null)
+ {
+ throw new ArgumentNullException("completedMethodInfo");
+ }
+ if (String.IsNullOrEmpty(actionName))
+ {
+ throw Error.ParameterCannotBeNullOrEmpty("actionName");
+ }
+ if (controllerDescriptor == null)
+ {
+ throw new ArgumentNullException("controllerDescriptor");
+ }
+
+ if (validateMethods)
+ {
+ string asyncFailedMessage = VerifyActionMethodIsCallable(asyncMethodInfo);
+ if (asyncFailedMessage != null)
+ {
+ throw new ArgumentException(asyncFailedMessage, "asyncMethodInfo");
+ }
+
+ string completedFailedMessage = VerifyActionMethodIsCallable(completedMethodInfo);
+ if (completedFailedMessage != null)
+ {
+ throw new ArgumentException(completedFailedMessage, "completedMethodInfo");
+ }
+ }
+
+ AsyncMethodInfo = asyncMethodInfo;
+ CompletedMethodInfo = completedMethodInfo;
+ _actionName = actionName;
+ _controllerDescriptor = controllerDescriptor;
+ _uniqueId = new Lazy<string>(CreateUniqueId);
+ }
+
+ public override string ActionName
+ {
+ get { return _actionName; }
+ }
+
+ public MethodInfo AsyncMethodInfo { get; private set; }
+
+ public MethodInfo CompletedMethodInfo { get; private set; }
+
+ public override ControllerDescriptor ControllerDescriptor
+ {
+ get { return _controllerDescriptor; }
+ }
+
+ public override string UniqueId
+ {
+ get { return _uniqueId.Value; }
+ }
+
+ public override IAsyncResult BeginExecute(ControllerContext controllerContext, IDictionary<string, object> parameters, AsyncCallback callback, object state)
+ {
+ if (controllerContext == null)
+ {
+ throw new ArgumentNullException("controllerContext");
+ }
+ if (parameters == null)
+ {
+ throw new ArgumentNullException("parameters");
+ }
+
+ AsyncManager asyncManager = GetAsyncManager(controllerContext.Controller);
+
+ BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState)
+ {
+ // call the XxxAsync() method
+ ParameterInfo[] parameterInfos = AsyncMethodInfo.GetParameters();
+ var rawParameterValues = from parameterInfo in parameterInfos
+ select ExtractParameterFromDictionary(parameterInfo, parameters, AsyncMethodInfo);
+ object[] parametersArray = rawParameterValues.ToArray();
+
+ TriggerListener listener = new TriggerListener();
+ SimpleAsyncResult asyncResult = new SimpleAsyncResult(asyncState);
+
+ // hook the Finished event to notify us upon completion
+ Trigger finishTrigger = listener.CreateTrigger();
+ asyncManager.Finished += delegate
+ {
+ finishTrigger.Fire();
+ };
+ asyncManager.OutstandingOperations.Increment();
+
+ // to simplify the logic, force the rest of the pipeline to execute in an asynchronous callback
+ listener.SetContinuation(() => ThreadPool.QueueUserWorkItem(_ => asyncResult.MarkCompleted(false /* completedSynchronously */, asyncCallback)));
+
+ // the inner operation might complete synchronously, so all setup work has to be done before this point
+ ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(AsyncMethodInfo);
+ dispatcher.Execute(controllerContext.Controller, parametersArray); // ignore return value from this method
+
+ // now that the XxxAsync() method has completed, kick off any pending operations
+ asyncManager.OutstandingOperations.Decrement();
+ listener.Activate();
+ return asyncResult;
+ };
+
+ EndInvokeDelegate<object> endDelegate = delegate(IAsyncResult asyncResult)
+ {
+ // call the XxxCompleted() method
+ ParameterInfo[] completionParametersInfos = CompletedMethodInfo.GetParameters();
+ var rawCompletionParameterValues = from parameterInfo in completionParametersInfos
+ select ExtractParameterOrDefaultFromDictionary(parameterInfo, asyncManager.Parameters);
+ object[] completionParametersArray = rawCompletionParameterValues.ToArray();
+
+ ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(CompletedMethodInfo);
+ object actionReturnValue = dispatcher.Execute(controllerContext.Controller, completionParametersArray);
+ return actionReturnValue;
+ };
+
+ return AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _executeTag, asyncManager.Timeout);
+ }
+
+ private string CreateUniqueId()
+ {
+ return base.UniqueId + DescriptorUtil.CreateUniqueId(AsyncMethodInfo, CompletedMethodInfo);
+ }
+
+ public override object EndExecute(IAsyncResult asyncResult)
+ {
+ return AsyncResultWrapper.End<object>(asyncResult, _executeTag);
+ }
+
+ public override object[] GetCustomAttributes(bool inherit)
+ {
+ return ActionDescriptorHelper.GetCustomAttributes(AsyncMethodInfo, inherit);
+ }
+
+ public override object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return ActionDescriptorHelper.GetCustomAttributes(AsyncMethodInfo, attributeType, inherit);
+ }
+
+ public override IEnumerable<FilterAttribute> GetFilterAttributes(bool useCache)
+ {
+ if (useCache && GetType() == typeof(ReflectedAsyncActionDescriptor))
+ {
+ // Do not look at cache in types derived from this type because they might incorrectly implement GetCustomAttributes
+ return ReflectedAttributeCache.GetMethodFilterAttributes(AsyncMethodInfo);
+ }
+ return base.GetFilterAttributes(useCache);
+ }
+
+ public override ParameterDescriptor[] GetParameters()
+ {
+ return ActionDescriptorHelper.GetParameters(this, AsyncMethodInfo, ref _parametersCache);
+ }
+
+ public override ICollection<ActionSelector> GetSelectors()
+ {
+ return ActionDescriptorHelper.GetSelectors(AsyncMethodInfo);
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ return ActionDescriptorHelper.IsDefined(AsyncMethodInfo, attributeType, inherit);
+ }
+ }
+}