From 09667e86ab23ee0ee76c48e79c3f823faabad6c2 Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Mon, 27 Mar 2017 09:19:08 -0700 Subject: [PATCH] Port ObjectMethodExecutor race fix --- .../Internal/ObjectMethodExecutor.cs | 86 +++++++++---------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/src/Microsoft.AspNetCore.SignalR/Internal/ObjectMethodExecutor.cs b/src/Microsoft.AspNetCore.SignalR/Internal/ObjectMethodExecutor.cs index bb34b4eb9b..ea19c0fb91 100644 --- a/src/Microsoft.AspNetCore.SignalR/Internal/ObjectMethodExecutor.cs +++ b/src/Microsoft.AspNetCore.SignalR/Internal/ObjectMethodExecutor.cs @@ -14,9 +14,9 @@ namespace Microsoft.AspNetCore.SignalR.Internal { internal class ObjectMethodExecutor { - private object[] _parameterDefaultValues; - private ActionExecutorAsync _executorAsync; - private ActionExecutor _executor; + private readonly object[] _parameterDefaultValues; + private readonly ActionExecutorAsync _executorAsync; + private readonly ActionExecutor _executor; private static readonly MethodInfo _convertOfTMethod = typeof(ObjectMethodExecutor).GetRuntimeMethods().Single(methodInfo => methodInfo.Name == nameof(ObjectMethodExecutor.Convert)); @@ -27,12 +27,26 @@ namespace Microsoft.AspNetCore.SignalR.Internal { throw new ArgumentNullException(nameof(methodInfo)); } + MethodInfo = methodInfo; TargetTypeInfo = targetTypeInfo; ActionParameters = methodInfo.GetParameters(); MethodReturnType = methodInfo.ReturnType; IsMethodAsync = typeof(Task).IsAssignableFrom(MethodReturnType); TaskGenericType = IsMethodAsync ? GetTaskInnerTypeOrNull(MethodReturnType) : null; + + if (IsMethodAsync && TaskGenericType != null) + { + // For backwards compatibility we're creating a sync-executor for an async method. + _executor = GetExecutor(methodInfo, targetTypeInfo); + _executorAsync = GetExecutorAsync(TaskGenericType, methodInfo, targetTypeInfo); + } + else + { + _executor = GetExecutor(methodInfo, targetTypeInfo); + } + + _parameterDefaultValues = GetParameterDefaultValues(ActionParameters); } private delegate Task ActionExecutorAsync(object target, object[] parameters); @@ -54,29 +68,15 @@ namespace Microsoft.AspNetCore.SignalR.Internal public bool IsMethodAsync { get; } - private ActionExecutorAsync TaskOfTActionExecutorAsync - { - get - { - if (_executorAsync == null) - { - _executorAsync = GetExecutorAsync(TaskGenericType, MethodInfo, TargetTypeInfo); - } - - return _executorAsync; - } - } - public static ObjectMethodExecutor Create(MethodInfo methodInfo, TypeInfo targetTypeInfo) { var executor = new ObjectMethodExecutor(methodInfo, targetTypeInfo); - executor._executor = GetExecutor(methodInfo, targetTypeInfo); return executor; } public Task ExecuteAsync(object target, object[] parameters) { - return TaskOfTActionExecutorAsync(target, parameters); + return _executorAsync(target, parameters); } public object Execute(object target, object[] parameters) @@ -91,8 +91,6 @@ namespace Microsoft.AspNetCore.SignalR.Internal throw new ArgumentOutOfRangeException(nameof(index)); } - EnsureParameterDefaultValues(); - return _parameterDefaultValues[index]; } @@ -221,42 +219,40 @@ namespace Microsoft.AspNetCore.SignalR.Internal return CastToObject(task); } - private void EnsureParameterDefaultValues() + private static object[] GetParameterDefaultValues(ParameterInfo[] parameters) { - if (_parameterDefaultValues == null) + var values = new object[parameters.Length]; + + for (var i = 0; i < parameters.Length; i++) { - var count = ActionParameters.Length; - _parameterDefaultValues = new object[count]; + var parameterInfo = parameters[i]; + object defaultValue; - for (var i = 0; i < count; i++) + if (parameterInfo.HasDefaultValue) { - var parameterInfo = ActionParameters[i]; - object defaultValue; - - if (parameterInfo.HasDefaultValue) + defaultValue = parameterInfo.DefaultValue; + } + else + { + var defaultValueAttribute = parameterInfo + .GetCustomAttribute(inherit: false); + + if (defaultValueAttribute?.Value == null) { - defaultValue = parameterInfo.DefaultValue; + defaultValue = parameterInfo.ParameterType.GetTypeInfo().IsValueType + ? Activator.CreateInstance(parameterInfo.ParameterType) + : null; } else { - var defaultValueAttribute = parameterInfo - .GetCustomAttribute(inherit: false); - - if (defaultValueAttribute?.Value == null) - { - defaultValue = parameterInfo.ParameterType.GetTypeInfo().IsValueType - ? Activator.CreateInstance(parameterInfo.ParameterType) - : null; - } - else - { - defaultValue = defaultValueAttribute.Value; - } + defaultValue = defaultValueAttribute.Value; } - - _parameterDefaultValues[i] = defaultValue; } + + values[i] = defaultValue; } + + return values; } } }