From 45468bc6634e9ba5518c1373e4a2ff1e4ddb91db Mon Sep 17 00:00:00 2001 From: Eric Rozell Date: Fri, 2 Mar 2018 22:33:54 -0500 Subject: [PATCH 1/2] perf(PropertySetter): Use generic delegate approach for view managers The recent work to avoid reflection for native modules can also be applied to native props for view managers (which also uses reflection). Avoiding reflection invoke saves quite a few cycles. This change extracts the logic from ReflectionReactDelegateFactory to create the IGenericDelegate, and adds support for generic delegates where the instance isn't known up-front. We need this because the ViewManager responsible for creating all the PropertySetters only holds a reference to the ShadowNode type, not the ShadowNode instance itself. --- .../Bridge/GenericDelegate.cs | 70 ++++++ .../Bridge/GenericDelegateTypes.cs | 230 ++++++++++++++---- .../Bridge/GenericDelegateTypes.tt | 13 +- .../Bridge/ReflectionReactDelegateFactory.cs | 48 +--- .../ReactNative.Shared.projitems | 1 + .../UIManager/PropertySetter.cs | 77 +++--- 6 files changed, 313 insertions(+), 126 deletions(-) create mode 100644 ReactWindows/ReactNative.Shared/Bridge/GenericDelegate.cs diff --git a/ReactWindows/ReactNative.Shared/Bridge/GenericDelegate.cs b/ReactWindows/ReactNative.Shared/Bridge/GenericDelegate.cs new file mode 100644 index 00000000000..23762f6f69e --- /dev/null +++ b/ReactWindows/ReactNative.Shared/Bridge/GenericDelegate.cs @@ -0,0 +1,70 @@ +using System; +using System.Reflection; + +namespace ReactNative.Bridge +{ + static class GenericDelegate + { + public static IGenericDelegate Create(MethodInfo method) + { + return (IGenericDelegate)Activator.CreateInstance(CreateDelegateType(method, false), method); + } + + public static IGenericDelegate Create(object instance, MethodInfo method) + { + return (IGenericDelegate)Activator.CreateInstance(CreateDelegateType(method, true), instance, method); + } + + private static Type CreateDelegateType(MethodInfo method, bool withInstance) + { + var methodParameters = method.GetParameters(); + var hasReturnValue = method.ReturnType != typeof(void); + var maximumParameterCount = hasReturnValue ? GenericDelegateTypes.FuncTypes.Length : GenericDelegateTypes.ActionTypes.Length; + + // If the number of arguments exceeds the number supported by generic delegates, + // return null. This will fall back to using reflection. + var thisArgumentCount = withInstance ? 0 : 1; + var argumentCount = methodParameters.Length + thisArgumentCount; + if (argumentCount > maximumParameterCount) + { + return null; + } + + // Increment the generic arity for methods with return values. + var genericArity = hasReturnValue ? argumentCount + 1 : argumentCount; + var typeList = new Type[genericArity]; + + // Set the first generic parameter to the declaring type, if necessary + if (!withInstance) + { + typeList[0] = method.DeclaringType; + } + + // Fill the generic type parameter list with method parameter types. + for (int t = thisArgumentCount; t < argumentCount; t++) + { + typeList[t] = methodParameters[t - thisArgumentCount].ParameterType; + } + + // If the function has a return value, append it to the generic type parameters. + if (hasReturnValue) + { + typeList[argumentCount] = method.ReturnType; + } + + // Get the appropriate generic delegate type. + var genericDelegateType = hasReturnValue + ? GenericDelegateTypes.FuncTypes[argumentCount] + : GenericDelegateTypes.ActionTypes[argumentCount]; + + // Close the generic type over the argument and return types, if necessary. + var delegateType = genericDelegateType; + if (genericArity > 0) + { + delegateType = genericDelegateType.MakeGenericType(typeList); + } + + return delegateType; + } + } +} diff --git a/ReactWindows/ReactNative.Shared/Bridge/GenericDelegateTypes.cs b/ReactWindows/ReactNative.Shared/Bridge/GenericDelegateTypes.cs index b0361030813..ecfce3fa508 100644 --- a/ReactWindows/ReactNative.Shared/Bridge/GenericDelegateTypes.cs +++ b/ReactWindows/ReactNative.Shared/Bridge/GenericDelegateTypes.cs @@ -1,7 +1,6 @@ // // This file is generated by GenericDelegateTypes.tt // - using System; using System.Reflection; @@ -28,7 +27,6 @@ static class GenericDelegateTypes typeof(SignatureAction14<,,,,,,,,,,,,,>), typeof(SignatureAction15<,,,,,,,,,,,,,,>), typeof(SignatureAction16<,,,,,,,,,,,,,,,>), - }; public static Type[] FuncTypes = @@ -50,23 +48,25 @@ static class GenericDelegateTypes typeof(SignatureFunc14<,,,,,,,,,,,,,,>), typeof(SignatureFunc15<,,,,,,,,,,,,,,,>), typeof(SignatureFunc16<,,,,,,,,,,,,,,,,>), - }; class SignatureAction0 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction0(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction0(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); } - public object DelegateTarget => _instancedDelegate.Target; - public object Invoke(object[] args) { - _instancedDelegate(); + _instancedDelegate(); return null; } } @@ -75,31 +75,36 @@ class SignatureFunc0 : IGenericDelegate { Func _instancedDelegate; + public SignatureFunc0(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc0(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); } - public object DelegateTarget => _instancedDelegate.Target; - public object Invoke(object[] args) => _instancedDelegate(); } - class SignatureAction1 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction1(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction1(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); } - public object DelegateTarget => _instancedDelegate.Target; - public object Invoke(object[] args) { - _instancedDelegate((T0)args[0]); + _instancedDelegate((T0)args[0]); return null; } } @@ -108,6 +113,11 @@ class SignatureFunc1 : IGenericDelegate { Func _instancedDelegate; + public SignatureFunc1(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc1(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -116,11 +126,15 @@ public SignatureFunc1(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0]); } - class SignatureAction2 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction2(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction2(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -128,7 +142,7 @@ public SignatureAction2(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1]); + _instancedDelegate((T0)args[0], (T1)args[1]); return null; } } @@ -137,6 +151,11 @@ class SignatureFunc2 : IGenericDelegate { Func _instancedDelegate; + public SignatureFunc2(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc2(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -145,11 +164,15 @@ public SignatureFunc2(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1]); } - class SignatureAction3 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction3(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction3(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -157,7 +180,7 @@ public SignatureAction3(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2]); return null; } } @@ -166,6 +189,11 @@ class SignatureFunc3 : IGenericDelegate { Func _instancedDelegate; + public SignatureFunc3(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc3(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -174,11 +202,15 @@ public SignatureFunc3(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2]); } - class SignatureAction4 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction4(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction4(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -186,7 +218,7 @@ public SignatureAction4(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3]); return null; } } @@ -195,6 +227,11 @@ class SignatureFunc4 : IGenericDelegate { Func _instancedDelegate; + public SignatureFunc4(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc4(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -203,11 +240,15 @@ public SignatureFunc4(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3]); } - class SignatureAction5 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction5(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction5(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -215,7 +256,7 @@ public SignatureAction5(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4]); return null; } } @@ -224,6 +265,11 @@ class SignatureFunc5 : IGenericDelegate { Func _instancedDelegate; + public SignatureFunc5(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc5(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -232,11 +278,15 @@ public SignatureFunc5(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4]); } - class SignatureAction6 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction6(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction6(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -244,7 +294,7 @@ public SignatureAction6(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5]); return null; } } @@ -253,6 +303,11 @@ class SignatureFunc6 : IGenericDelegate { Func _instancedDelegate; + public SignatureFunc6(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc6(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -261,11 +316,15 @@ public SignatureFunc6(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5]); } - class SignatureAction7 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction7(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction7(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -273,7 +332,7 @@ public SignatureAction7(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6]); return null; } } @@ -282,6 +341,11 @@ class SignatureFunc7 : IGenericDelegate { Func _instancedDelegate; + public SignatureFunc7(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc7(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -290,11 +354,15 @@ public SignatureFunc7(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6]); } - class SignatureAction8 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction8(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction8(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -302,7 +370,7 @@ public SignatureAction8(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7]); return null; } } @@ -311,6 +379,11 @@ class SignatureFunc8 : IGenericDelegate { Func _instancedDelegate; + public SignatureFunc8(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc8(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -319,11 +392,15 @@ public SignatureFunc8(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7]); } - class SignatureAction9 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction9(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction9(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -331,7 +408,7 @@ public SignatureAction9(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8]); return null; } } @@ -340,6 +417,11 @@ class SignatureFunc9 : IGenericDele { Func _instancedDelegate; + public SignatureFunc9(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc9(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -348,11 +430,15 @@ public SignatureFunc9(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8]); } - class SignatureAction10 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction10(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction10(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -360,7 +446,7 @@ public SignatureAction10(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9]); return null; } } @@ -369,6 +455,11 @@ class SignatureFunc10 : IGeneri { Func _instancedDelegate; + public SignatureFunc10(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc10(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -377,11 +468,15 @@ public SignatureFunc10(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9]); } - class SignatureAction11 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction11(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction11(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -389,7 +484,7 @@ public SignatureAction11(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10]); return null; } } @@ -398,6 +493,11 @@ class SignatureFunc11 : IG { Func _instancedDelegate; + public SignatureFunc11(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc11(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -406,11 +506,15 @@ public SignatureFunc11(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10]); } - class SignatureAction12 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction12(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction12(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -418,7 +522,7 @@ public SignatureAction12(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11]); return null; } } @@ -427,6 +531,11 @@ class SignatureFunc12 { Func _instancedDelegate; + public SignatureFunc12(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc12(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -435,11 +544,15 @@ public SignatureFunc12(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11]); } - class SignatureAction13 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction13(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction13(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -447,7 +560,7 @@ public SignatureAction13(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11], (T12)args[12]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11], (T12)args[12]); return null; } } @@ -456,6 +569,11 @@ class SignatureFunc13 _instancedDelegate; + public SignatureFunc13(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc13(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -464,11 +582,15 @@ public SignatureFunc13(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11], (T12)args[12]); } - class SignatureAction14 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction14(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction14(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -476,7 +598,7 @@ public SignatureAction14(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11], (T12)args[12], (T13)args[13]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11], (T12)args[12], (T13)args[13]); return null; } } @@ -485,6 +607,11 @@ class SignatureFunc14 _instancedDelegate; + public SignatureFunc14(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc14(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -493,11 +620,15 @@ public SignatureFunc14(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11], (T12)args[12], (T13)args[13]); } - class SignatureAction15 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction15(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction15(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -505,7 +636,7 @@ public SignatureAction15(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11], (T12)args[12], (T13)args[13], (T14)args[14]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11], (T12)args[12], (T13)args[13], (T14)args[14]); return null; } } @@ -514,6 +645,11 @@ class SignatureFunc15 _instancedDelegate; + public SignatureFunc15(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc15(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -522,11 +658,15 @@ public SignatureFunc15(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11], (T12)args[12], (T13)args[13], (T14)args[14]); } - class SignatureAction16 : IGenericDelegate { Action _instancedDelegate; + public SignatureAction16(MethodInfo method) + { + _instancedDelegate = (Action)method.CreateDelegate(typeof(Action)); + } + public SignatureAction16(object instance, MethodInfo method) { _instancedDelegate = (Action)method.CreateDelegate(typeof(Action), instance); @@ -534,7 +674,7 @@ public SignatureAction16(object instance, MethodInfo method) public object Invoke(object[] args) { - _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11], (T12)args[12], (T13)args[13], (T14)args[14], (T15)args[15]); + _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11], (T12)args[12], (T13)args[13], (T14)args[14], (T15)args[15]); return null; } } @@ -543,6 +683,11 @@ class SignatureFunc16 _instancedDelegate; + public SignatureFunc16(MethodInfo method) + { + _instancedDelegate = (Func)method.CreateDelegate(typeof(Func)); + } + public SignatureFunc16(object instance, MethodInfo method) { _instancedDelegate = (Func)method.CreateDelegate(typeof(Func), instance); @@ -551,6 +696,5 @@ public SignatureFunc16(object instance, MethodInfo method) public object Invoke(object[] args) => _instancedDelegate((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3], (T4)args[4], (T5)args[5], (T6)args[6], (T7)args[7], (T8)args[8], (T9)args[9], (T10)args[10], (T11)args[11], (T12)args[12], (T13)args[13], (T14)args[14], (T15)args[15]); } - } } diff --git a/ReactWindows/ReactNative.Shared/Bridge/GenericDelegateTypes.tt b/ReactWindows/ReactNative.Shared/Bridge/GenericDelegateTypes.tt index 145793416bd..b04aa49fc66 100644 --- a/ReactWindows/ReactNative.Shared/Bridge/GenericDelegateTypes.tt +++ b/ReactWindows/ReactNative.Shared/Bridge/GenericDelegateTypes.tt @@ -13,7 +13,7 @@ using System.Reflection; namespace ReactNative.Bridge { - static class GenericDelegateType + static class GenericDelegateTypes { public static Type[] ActionTypes = { @@ -54,10 +54,16 @@ for (var i = 0; i <= maxArity; ++i) funcTypeParamsString = funcTypeParamsString + ", "; } #> + class SignatureAction<#=i#><#=actionTypeParamsString#> : IGenericDelegate { Action<#=actionTypeParamsString#> _instancedDelegate; + public SignatureAction<#=i#>(MethodInfo method) + { + _instancedDelegate = (Action<#=actionTypeParamsString#>)method.CreateDelegate(typeof(Action<#=actionTypeParamsString#>)); + } + public SignatureAction<#=i#>(object instance, MethodInfo method) { _instancedDelegate = (Action<#=actionTypeParamsString#>)method.CreateDelegate(typeof(Action<#=actionTypeParamsString#>), instance); @@ -74,6 +80,11 @@ for (var i = 0; i <= maxArity; ++i) { Func<<#=funcTypeParamsString#>TResult> _instancedDelegate; + public SignatureFunc<#=i#>(MethodInfo method) + { + _instancedDelegate = (Func<<#=funcTypeParamsString#>TResult>)method.CreateDelegate(typeof(Func<<#=funcTypeParamsString#>TResult>)); + } + public SignatureFunc<#=i#>(object instance, MethodInfo method) { _instancedDelegate = (Func<<#=funcTypeParamsString#>TResult>)method.CreateDelegate(typeof(Func<<#=funcTypeParamsString#>TResult>), instance); diff --git a/ReactWindows/ReactNative.Shared/Bridge/ReflectionReactDelegateFactory.cs b/ReactWindows/ReactNative.Shared/Bridge/ReflectionReactDelegateFactory.cs index 0b0dafa8740..f3d40eb254b 100644 --- a/ReactWindows/ReactNative.Shared/Bridge/ReflectionReactDelegateFactory.cs +++ b/ReactWindows/ReactNative.Shared/Bridge/ReflectionReactDelegateFactory.cs @@ -31,7 +31,7 @@ public override Action Create(INativeModule module, Meth var extractors = CreateExtractors(module, method); var expectedArguments = extractors.Sum(e => e.ExpectedArguments); var extractFunctions = extractors.Select(e => e.ExtractFunction).ToList(); - var genericDelegate = CreateGenericDelegate(module, method); + var genericDelegate = GenericDelegate.Create(module, method); return (reactInstance, arguments) => Invoke( @@ -179,52 +179,6 @@ private static void Invoke( } } - static IGenericDelegate CreateGenericDelegate(object instance, MethodInfo method) - { - var methodParameters = method.GetParameters(); - var hasReturnValue = method.ReturnType != typeof(void); - var maximumParameterCount = hasReturnValue ? GenericDelegateTypes.FuncTypes.Length : GenericDelegateTypes.ActionTypes.Length; - - // If the number of arguments exceeds the number supported by generic delegates, - // return null. This will fall back to using reflection. - var argumentCount = methodParameters.Length; - if (argumentCount > maximumParameterCount) - { - return null; - } - - // Increment the generic arity for methods with return values. - var genericArity = hasReturnValue ? argumentCount + 1 : argumentCount; - var typeList = new Type[genericArity]; - - // Fill the generic type parameter list with method parameter types. - for (int t = 0; t < argumentCount; t++) - { - typeList[t] = methodParameters[t].ParameterType; - } - - // If the function has a return value, append it to the generic type parameters. - if (hasReturnValue) - { - typeList[argumentCount] = method.ReturnType; - } - - // Get the appropriate generic delegate type. - var genericDelegateType = hasReturnValue - ? GenericDelegateTypes.FuncTypes[argumentCount] - : GenericDelegateTypes.ActionTypes[argumentCount]; - - // Close the generic type over the argument and return types, if necessary. - var delegateType = genericDelegateType; - if (genericArity > 0) - { - delegateType = genericDelegateType.MakeGenericType(typeList); - } - - // Create the generic delegate instance. - return (IGenericDelegate)Activator.CreateInstance(delegateType, instance, method); - } - private struct Result { public Result(int nextIndex, object value) diff --git a/ReactWindows/ReactNative.Shared/ReactNative.Shared.projitems b/ReactWindows/ReactNative.Shared/ReactNative.Shared.projitems index 289d96a3424..66942f10d4e 100644 --- a/ReactWindows/ReactNative.Shared/ReactNative.Shared.projitems +++ b/ReactWindows/ReactNative.Shared/ReactNative.Shared.projitems @@ -28,6 +28,7 @@ + diff --git a/ReactWindows/ReactNative.Shared/UIManager/PropertySetter.cs b/ReactWindows/ReactNative.Shared/UIManager/PropertySetter.cs index fb239918d0d..6909391d322 100644 --- a/ReactWindows/ReactNative.Shared/UIManager/PropertySetter.cs +++ b/ReactWindows/ReactNative.Shared/UIManager/PropertySetter.cs @@ -1,7 +1,7 @@ +using ReactNative.Bridge; using ReactNative.UIManager.Annotations; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Reflection; using System.Threading; #if WINDOWS_UWP @@ -47,6 +47,7 @@ abstract class PropertySetter : IPropertySetter { typeof(bool), a => a.DefaultBoolean }, }; + private readonly IGenericDelegate _genericDelegate; private readonly ReactPropBaseAttribute _attribute; private readonly string _propertyType; @@ -56,6 +57,8 @@ protected PropertySetter(MethodInfo method, string name, ReactPropBaseAttribute Name = name; PropertyType = GetPropertyType(method); + _genericDelegate = GenericDelegate.Create(method); + _propertyType = attribute.CustomType == ReactPropBaseAttribute.UseDefaultType ? GetPropertyType(PropertyType) : attribute.CustomType; @@ -84,7 +87,7 @@ public void UpdateShadowNodeProperty(ReactShadowNode shadowNode, ReactStylesDiff if (props == null) throw new ArgumentNullException(nameof(props)); - Invoke(shadowNode, GetShadowNodeArgs(props)); + Invoke(GetShadowNodeArgs(shadowNode, props)); } public void UpdateViewManagerProperty(IViewManager viewManager, DependencyObject view, ReactStylesDiffMap props) @@ -94,15 +97,15 @@ public void UpdateViewManagerProperty(IViewManager viewManager, DependencyObject if (props == null) throw new ArgumentNullException(nameof(props)); - Invoke(viewManager, GetViewManagerArgs(view, props)); + Invoke(GetViewManagerArgs(viewManager, view, props)); } - protected virtual object[] GetShadowNodeArgs(ReactStylesDiffMap props) + protected virtual object[] GetShadowNodeArgs(ReactShadowNode shadowNode, ReactStylesDiffMap props) { throw new NotSupportedException(Invariant($"'{nameof(ReactShadowNode)}' properties cannot be changed with this setter.")); } - protected virtual object[] GetViewManagerArgs(DependencyObject view, ReactStylesDiffMap props) + protected virtual object[] GetViewManagerArgs(IViewManager viewManager, DependencyObject view, ReactStylesDiffMap props) { throw new NotSupportedException($"'{nameof(IViewManager)}' properties cannot be changed with this setter."); } @@ -124,15 +127,11 @@ protected object ExtractProperty(ReactStylesDiffMap props) .ToObject(PropertyType); } - private void Invoke(object instance, object[] args) + private void Invoke(object[] args) { try { - Method.Invoke(instance, args); - } - catch (TargetInvocationException ex) - { - throw ex.InnerException; + _genericDelegate.Invoke(args); } finally { @@ -215,7 +214,7 @@ public static IEnumerable CreateViewManagerSetters(MethodInfo m class ViewManagerPropertySetter : PropertySetter { - private static ThreadLocal s_args = new ThreadLocal(() => new object[2]); + private static ThreadLocal s_args = new ThreadLocal(() => new object[3]); public ViewManagerPropertySetter(MethodInfo method, string name, ReactPropBaseAttribute attribute) : base(method, name, attribute) @@ -240,22 +239,24 @@ protected override Type GetPropertyType(MethodInfo method) return parameters[1].ParameterType; } - protected override object[] GetViewManagerArgs(DependencyObject view, ReactStylesDiffMap props) + protected override object[] GetViewManagerArgs(IViewManager viewManager, DependencyObject view, ReactStylesDiffMap props) { - s_args.Value[0] = view; - s_args.Value[1] = ExtractProperty(props); - return s_args.Value; + var args = s_args.Value; + args[0] = viewManager; + args[1] = view; + args[2] = ExtractProperty(props); + return args; } protected override void OnInvoked() { - Array.Clear(s_args.Value, 0, 2); + Array.Clear(s_args.Value, 0, 3); } } class ViewManagerGroupPropertySetter : PropertySetter { - private static ThreadLocal s_args = new ThreadLocal(() => new object[3]); + private static ThreadLocal s_args = new ThreadLocal(() => new object[4]); private readonly int _index; @@ -290,23 +291,25 @@ protected override Type GetPropertyType(MethodInfo method) return parameters[2].ParameterType; } - protected override object[] GetViewManagerArgs(DependencyObject view, ReactStylesDiffMap props) + protected override object[] GetViewManagerArgs(IViewManager viewManager, DependencyObject view, ReactStylesDiffMap props) { - s_args.Value[0] = view; - s_args.Value[1] = _index; - s_args.Value[2] = ExtractProperty(props); - return s_args.Value; + var args = s_args.Value; + args[0] = viewManager; + args[1] = view; + args[2] = _index; + args[3] = ExtractProperty(props); + return args; } protected override void OnInvoked() { - Array.Clear(s_args.Value, 0, 3); + Array.Clear(s_args.Value, 0, 4); } } class ShadowNodePropertySetter : PropertySetter { - private static ThreadLocal s_args = new ThreadLocal(() => new object[1]); + private static ThreadLocal s_args = new ThreadLocal(() => new object[2]); public ShadowNodePropertySetter(MethodInfo method, string name, ReactPropBaseAttribute attribute) : base(method, name, attribute) @@ -325,21 +328,23 @@ protected override Type GetPropertyType(MethodInfo method) return parameters[0].ParameterType; } - protected override object[] GetShadowNodeArgs(ReactStylesDiffMap props) + protected override object[] GetShadowNodeArgs(ReactShadowNode shadowNode, ReactStylesDiffMap props) { - s_args.Value[0] = ExtractProperty(props); - return s_args.Value; + var args = s_args.Value; + args[0] = shadowNode; + args[1] = ExtractProperty(props); + return args; } protected override void OnInvoked() { - Array.Clear(s_args.Value, 0, 1); + Array.Clear(s_args.Value, 0, 2); } } class ShadowNodeGroupPropertySetter : PropertySetter { - private static ThreadLocal s_args = new ThreadLocal(() => new object[2]); + private static ThreadLocal s_args = new ThreadLocal(() => new object[3]); private readonly int _index; @@ -367,16 +372,18 @@ protected override Type GetPropertyType(MethodInfo method) return parameters[1].ParameterType; } - protected override object[] GetShadowNodeArgs(ReactStylesDiffMap props) + protected override object[] GetShadowNodeArgs(ReactShadowNode shadowNode, ReactStylesDiffMap props) { - s_args.Value[0] = _index; - s_args.Value[1] = ExtractProperty(props); - return s_args.Value; + var args = s_args.Value; + args[0] = shadowNode; + args[1] = _index; + args[2] = ExtractProperty(props); + return args; } protected override void OnInvoked() { - Array.Clear(s_args.Value, 0, 2); + Array.Clear(s_args.Value, 0, 3); } } } From 04062d7b34270a07cc6e4f986bea4e983ef5aa45 Mon Sep 17 00:00:00 2001 From: Eric Rozell Date: Fri, 2 Mar 2018 23:54:46 -0500 Subject: [PATCH 2/2] fix(PropertySetter): replace reflection behavior Reflection invoke automatically converts null arguments to default struct values. We have to do something similar here when we avoid reflection invoke. --- .../ReactNative.Shared/UIManager/PropertySetter.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ReactWindows/ReactNative.Shared/UIManager/PropertySetter.cs b/ReactWindows/ReactNative.Shared/UIManager/PropertySetter.cs index 6909391d322..b247382fc5a 100644 --- a/ReactWindows/ReactNative.Shared/UIManager/PropertySetter.cs +++ b/ReactWindows/ReactNative.Shared/UIManager/PropertySetter.cs @@ -123,8 +123,15 @@ protected object ExtractProperty(ReactStylesDiffMap props) return defaultFunc(_attribute); } - return props.GetProperty(Name)? + var prop = props.GetProperty(Name)? .ToObject(PropertyType); + + if (prop == null && PropertyType.GetTypeInfo().IsValueType) + { + return Activator.CreateInstance(PropertyType); + } + + return prop; } private void Invoke(object[] args)