From 80ff55dcc9c77b5734b3c152c538af351c7e2dd2 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Mon, 27 Apr 2020 09:41:44 -0700 Subject: [PATCH] Added C# ReactContext for Module Initialize method (#4722) * Added C# ReactContext for Module Initialize method * Change files * Fixed sample project compilation --- ...020-04-26-21-09-42-MS_Cs_ReactContext.json | 8 + .../windows/SampleLibraryCS/SampleModuleCS.cs | 2 +- .../Microsoft.ReactNative.Cxx/NativeModules.h | 4 + .../Microsoft.ReactNative.Cxx/ReactContext.h | 6 + .../NativeModuleTest.cs | 2 +- .../NoAttributeNativeModuleTest.cs | 19 +- .../AttributedViewManager.cs | 5 +- .../JSValueGenerator.cs | 67 +++---- ...rosoft.ReactNative.SharedManaged.projitems | 2 +- .../ReactConstantProvider.cs | 10 +- .../ReactContext.cs | 176 ++++++++++++++++++ .../ReactContextExtensions.cs | 145 --------------- .../ReactContextGenerator.cs | 17 +- .../ReactEventInfo.cs | 6 +- .../ReactFunctionInfo.cs | 6 +- .../ReactInitializerInfo.cs | 7 +- 16 files changed, 258 insertions(+), 224 deletions(-) create mode 100644 change/react-native-windows-2020-04-26-21-09-42-MS_Cs_ReactContext.json create mode 100644 vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs delete mode 100644 vnext/Microsoft.ReactNative.SharedManaged/ReactContextExtensions.cs diff --git a/change/react-native-windows-2020-04-26-21-09-42-MS_Cs_ReactContext.json b/change/react-native-windows-2020-04-26-21-09-42-MS_Cs_ReactContext.json new file mode 100644 index 00000000000..76cefbe6c3f --- /dev/null +++ b/change/react-native-windows-2020-04-26-21-09-42-MS_Cs_ReactContext.json @@ -0,0 +1,8 @@ +{ + "type": "prerelease", + "comment": "Added C# ReactContext for Module Initialize method", + "packageName": "react-native-windows", + "email": "vmorozov@microsoft.com", + "dependentChangeType": "patch", + "date": "2020-04-27T04:09:42.583Z" +} diff --git a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs index 44a7d049b27..cd40e29bd09 100644 --- a/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs +++ b/packages/microsoft-reactnative-sampleapps/windows/SampleLibraryCS/SampleModuleCS.cs @@ -25,7 +25,7 @@ internal sealed class SampleModuleCS #region Initializer [ReactInitializer] - public void Initialize(IReactContext _) + public void Initialize(ReactContext _) { _timer = ThreadPoolTimer.CreatePeriodicTimer(new TimerElapsedHandler((timer) => { diff --git a/vnext/Microsoft.ReactNative.Cxx/NativeModules.h b/vnext/Microsoft.ReactNative.Cxx/NativeModules.h index 65d82ca9ba2..d7ab009b8c5 100644 --- a/vnext/Microsoft.ReactNative.Cxx/NativeModules.h +++ b/vnext/Microsoft.ReactNative.Cxx/NativeModules.h @@ -694,6 +694,10 @@ struct ReactConstantProvider { WriteProperty(m_writer, name, value); } + IJSValueWriter const &Writer() const noexcept { + return m_writer; + } + private: IJSValueWriter m_writer; }; diff --git a/vnext/Microsoft.ReactNative.Cxx/ReactContext.h b/vnext/Microsoft.ReactNative.Cxx/ReactContext.h index eee48e1569d..72dd33e5bda 100644 --- a/vnext/Microsoft.ReactNative.Cxx/ReactContext.h +++ b/vnext/Microsoft.ReactNative.Cxx/ReactContext.h @@ -17,6 +17,8 @@ namespace winrt::Microsoft::ReactNative { struct ReactContext { ReactContext(IReactContext const &context) noexcept; + IReactContext const &ContextAbi() const noexcept; + explicit operator bool() noexcept; template @@ -56,6 +58,10 @@ struct ReactContext { inline ReactContext::ReactContext(IReactContext const &context) noexcept : m_context{context} {} +inline IReactContext const &ReactContext::ContextAbi() const noexcept { + return m_context; +} + inline ReactContext::operator bool() noexcept { return m_context != nullptr; } diff --git a/vnext/Microsoft.ReactNative.Managed.UnitTests/NativeModuleTest.cs b/vnext/Microsoft.ReactNative.Managed.UnitTests/NativeModuleTest.cs index 98f48a7127d..06ab0e8a6db 100644 --- a/vnext/Microsoft.ReactNative.Managed.UnitTests/NativeModuleTest.cs +++ b/vnext/Microsoft.ReactNative.Managed.UnitTests/NativeModuleTest.cs @@ -20,7 +20,7 @@ public struct Point class SimpleNativeModule { [ReactInitializer] - public void Initialize(IReactContext context) + public void Initialize(ReactContext context) { IsInitialized = true; Assert.IsNotNull(context); diff --git a/vnext/Microsoft.ReactNative.Managed.UnitTests/NoAttributeNativeModuleTest.cs b/vnext/Microsoft.ReactNative.Managed.UnitTests/NoAttributeNativeModuleTest.cs index 43ccc114a80..f1863b1fd59 100644 --- a/vnext/Microsoft.ReactNative.Managed.UnitTests/NoAttributeNativeModuleTest.cs +++ b/vnext/Microsoft.ReactNative.Managed.UnitTests/NoAttributeNativeModuleTest.cs @@ -687,43 +687,48 @@ public void AddConstantProvider(Func> get public void AddJSEvent(string eventEmitterName, string name, Action setEventHandler) { m_moduleBuilder.AddInitializer(reactContext => { - setEventHandler(m_module, () => reactContext.EmitJSEvent(eventEmitterName ?? EventEmitterName ?? "RCTDeviceEventEmitter", name)); + setEventHandler(m_module, () => new ReactContext(reactContext).EmitJSEvent( + eventEmitterName ?? EventEmitterName ?? "RCTDeviceEventEmitter", name)); }); } public void AddJSEvent(string eventEmitterName, string name, Action> setEventHandler) { m_moduleBuilder.AddInitializer(reactContext => { - setEventHandler(m_module, (T1 arg1) => reactContext.EmitJSEvent(eventEmitterName ?? EventEmitterName ?? "RCTDeviceEventEmitter", name, arg1)); + setEventHandler(m_module, (T1 arg1) => new ReactContext(reactContext).EmitJSEvent( + eventEmitterName ?? EventEmitterName ?? "RCTDeviceEventEmitter", name, arg1)); }); } public void AddJSEvent(string eventEmitterName, string name, Action> setEventHandler) { m_moduleBuilder.AddInitializer(reactContext => { - setEventHandler(m_module, (T1 arg1, T2 arg2) => - reactContext.EmitJSEvent(eventEmitterName ?? EventEmitterName ?? "RCTDeviceEventEmitter", name, arg1, arg2)); + setEventHandler(m_module, (T1 arg1, T2 arg2) => new ReactContext(reactContext).EmitJSEvent( + eventEmitterName ?? EventEmitterName ?? "RCTDeviceEventEmitter", name, arg1, arg2)); }); } public void AddJSFunction(string moduleName, string name, Action setFunctionHandler) { m_moduleBuilder.AddInitializer(reactContext => { - setFunctionHandler(m_module, () => reactContext.CallJSFunction(moduleName ?? ModuleName, name)); + setFunctionHandler(m_module, () => new ReactContext(reactContext).CallJSFunction( + moduleName ?? ModuleName, name)); }); } public void AddJSFunction(string moduleName, string name, Action> setFunctionHandler) { m_moduleBuilder.AddInitializer(reactContext => { - setFunctionHandler(m_module, (T1 arg1) => reactContext.CallJSFunction(moduleName ?? ModuleName, name, arg1)); + setFunctionHandler(m_module, (T1 arg1) => new ReactContext(reactContext).CallJSFunction( + moduleName ?? ModuleName, name, arg1)); }); } public void AddJSFunction(string moduleName, string name, Action> setFunctionHandler) { m_moduleBuilder.AddInitializer(reactContext => { - setFunctionHandler(m_module, (T1 arg1, T2 arg2) => reactContext.CallJSFunction(moduleName ?? ModuleName, name, arg1, arg2)); + setFunctionHandler(m_module, (T1 arg1, T2 arg2) => new ReactContext(reactContext).CallJSFunction( + moduleName ?? ModuleName, name, arg1, arg2)); }); } diff --git a/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs b/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs index 56691b2be2f..ab835d574ae 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/AttributedViewManager.cs @@ -402,8 +402,9 @@ private Delegate MakeEventDelegate(string eventName, Type memberType, Type event ParameterExpression eventDataParameter = Expression.Parameter(eventDataType, "eventData"); MemberExpression thisReactContext = Expression.Property(Expression.Constant(this), "ReactContext"); - MethodCallExpression dispatchCall = Expression.Call(DispatchEventOf(eventDataType), - thisReactContext, + NewExpression reactContext = Expression.New(ReactContextConstructor(), thisReactContext); + MethodCallExpression dispatchCall = Expression.Call(reactContext, + DispatchEventOf(eventDataType), viewParameter, Expression.Constant(eventName, typeof(string)), eventDataParameter); diff --git a/vnext/Microsoft.ReactNative.SharedManaged/JSValueGenerator.cs b/vnext/Microsoft.ReactNative.SharedManaged/JSValueGenerator.cs index 13e1db92ca9..eaa35d5c61a 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/JSValueGenerator.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/JSValueGenerator.cs @@ -212,66 +212,41 @@ public Expression Assign(Expression value) return Expression.Assign(AsExpression, value); } - public Expression Call(MethodInfo method, params Expression[] args) + // This method allows us to expand the argument array that may use parameters that are + // Expressions, VariableWrappers, or arrays of them. + // The argument expressions are added to the args list. + private void ExpandArgArray(IList args, object[] argObjects) { - return Expression.Call(AsExpression, method, args); - } - - public Expression Call(string methodName, params Expression[] args) - { - return Call(Type.GetMethod(methodName), args); - } - - public Expression CallExt(MethodInfo method) - { - return Expression.Call(method, AsExpression); - } - - public Expression CallExt(MethodInfo method, Expression arg0) - { - return Expression.Call(method, AsExpression, arg0); - } - - public Expression CallExt(MethodInfo method, Expression arg0, Expression arg1) - { - return Expression.Call(method, AsExpression, arg0, arg1); - } - - public Expression CallExt(MethodInfo method, params Expression[] args) - { - return Expression.Call(method, Enumerable.Repeat(AsExpression, 1).Concat(args)); + foreach (var arg in argObjects) + { + switch (arg) + { + case object[] items: ExpandArgArray(args, items); break; + case VariableWrapper variable: args.Add(variable.AsExpression); break; + case Expression expr: args.Add(expr); break; + } + } } - public Expression CallExt(MethodInfo method, params VariableWrapper[] args) + public MethodCallExpression Call(MethodInfo method, params object[] arguments) { - return Expression.Call(method, - Enumerable.Repeat(this, 1).Concat(args).Select(v => v.AsExpression)); + var args = new List(); + ExpandArgArray(args, arguments); + return Expression.Call(AsExpression, method, args); } public MethodCallExpression CallExt(MethodInfo method, params object[] arguments) { var args = new List { AsExpression }; - - void ParseArgs(object[] argObjects) - { - foreach (var arg in argObjects) - { - switch (arg) - { - case object[] items: ParseArgs(items); break; - case VariableWrapper variable: args.Add(variable.AsExpression); break; - case Expression expr: args.Add(expr); break; - } - } - } - - ParseArgs(arguments); + ExpandArgArray(args, arguments); return Expression.Call(method, args); } // It can be used only for delegate types - public Expression Invoke(params Expression[] args) + public Expression Invoke(params object[] arguments) { + var args = new List(); + ExpandArgArray(args, arguments); return Expression.Invoke(AsExpression, args); } diff --git a/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.projitems b/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.projitems index 20a1c82159a..49a4f0ca31b 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.projitems +++ b/vnext/Microsoft.ReactNative.SharedManaged/Microsoft.ReactNative.SharedManaged.projitems @@ -11,7 +11,7 @@ - + diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProvider.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProvider.cs index 87e65ed1e54..2d6a048cb79 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProvider.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactConstantProvider.cs @@ -3,18 +3,18 @@ namespace Microsoft.ReactNative.Managed { - class ReactConstantProvider + struct ReactConstantProvider { public ReactConstantProvider(IJSValueWriter writer) { - m_writer = writer; + Writer = writer; } + public IJSValueWriter Writer { get; } + public void Add(string constantName, T value) { - m_writer.WriteObjectProperty(constantName, value); + Writer.WriteObjectProperty(constantName, value); } - - private readonly IJSValueWriter m_writer; } } diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs new file mode 100644 index 00000000000..bfd8098550f --- /dev/null +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactContext.cs @@ -0,0 +1,176 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Windows.UI.Xaml; + +namespace Microsoft.ReactNative.Managed +{ + struct ReactContext + { + public ReactContext(IReactContext context) + { + ContextAbi = context; + } + + public IReactContext ContextAbi { get; } + + public void DispatchEvent(FrameworkElement view, string eventName, T arg) + { + var argWriter = arg as JSValueArgWriter; + if (argWriter != null) + { + ContextAbi.DispatchEvent(view, eventName, argWriter); + } + else + { + ContextAbi.DispatchEvent(view, eventName, (IJSValueWriter writer) => writer.WriteValue(arg)); + } + } + + public void CallJSFunction(string moduleName, string methodName) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs()); + } + + public void CallJSFunction(string moduleName, string methodName, T1 arg1) + { + var argWriter = arg1 as JSValueArgWriter; + if (argWriter != null) + { + ContextAbi.CallJSFunction(moduleName, methodName, argWriter); + } + else + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1)); + } + } + + public void CallJSFunction(string moduleName, string methodName, T1 arg1, T2 arg2) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2)); + } + + public void CallJSFunction(string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3)); + } + + public void CallJSFunction( + string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4)); + } + + public void CallJSFunction( + string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5)); + } + + public void CallJSFunction( + string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5, arg6)); + } + + public void CallJSFunction( + string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + ContextAbi.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5, arg6, arg7)); + } + + public void EmitJSEvent(string eventEmitterName, string eventName) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter _) => { }); + } + + public void EmitJSEvent(string eventEmitterName, string eventName, T1 arg1) + { + var argWriter = arg1 as JSValueArgWriter; + if (argWriter != null) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, argWriter); + } + else + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + }); + } + } + + public void EmitJSEvent(string eventEmitterName, string eventName, T1 arg1, T2 arg2) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + writer.WriteValue(arg2); + }); + } + + public void EmitJSEvent(string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + writer.WriteValue(arg2); + writer.WriteValue(arg3); + }); + } + + public void EmitJSEvent( + string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + writer.WriteValue(arg2); + writer.WriteValue(arg3); + writer.WriteValue(arg4); + }); + } + + public void EmitJSEvent( + string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + writer.WriteValue(arg2); + writer.WriteValue(arg3); + writer.WriteValue(arg4); + writer.WriteValue(arg5); + }); + } + + public void EmitJSEvent( + string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + writer.WriteValue(arg2); + writer.WriteValue(arg3); + writer.WriteValue(arg4); + writer.WriteValue(arg5); + writer.WriteValue(arg6); + }); + } + + public void EmitJSEvent( + string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + ContextAbi.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => + { + writer.WriteValue(arg1); + writer.WriteValue(arg2); + writer.WriteValue(arg3); + writer.WriteValue(arg4); + writer.WriteValue(arg5); + writer.WriteValue(arg6); + writer.WriteValue(arg7); + }); + } + } +} diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactContextExtensions.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactContextExtensions.cs deleted file mode 100644 index 9f1484be724..00000000000 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactContextExtensions.cs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Windows.UI.Xaml; - -namespace Microsoft.ReactNative.Managed -{ - static class ReactContextExtensions - { - public static void DispatchEvent(this IReactContext reactContext, FrameworkElement view, string eventName, T arg) - { - reactContext.DispatchEvent(view, eventName, (IJSValueWriter writer) => writer.WriteValue(arg)); - } - - public static void CallJSFunction(this IReactContext reactContext, string moduleName, string methodName) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs()); - } - - public static void CallJSFunction(this IReactContext reactContext, string moduleName, string methodName, T1 arg1) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1)); - } - - public static void CallJSFunction(this IReactContext reactContext, string moduleName, string methodName, T1 arg1, T2 arg2) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2)); - } - - public static void CallJSFunction(this IReactContext reactContext, string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3)); - } - - public static void CallJSFunction(this IReactContext reactContext, - string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4)); - } - - public static void CallJSFunction(this IReactContext reactContext, - string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5)); - } - - public static void CallJSFunction(this IReactContext reactContext, - string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5, arg6)); - } - - public static void CallJSFunction(this IReactContext reactContext, - string moduleName, string methodName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) - { - reactContext.CallJSFunction(moduleName, methodName, (IJSValueWriter writer) => writer.WriteArgs(arg1, arg2, arg3, arg4, arg5, arg6, arg7)); - } - - public static void EmitJSEvent(this IReactContext reactContext, string eventEmitterName, string eventName) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => {}); - } - - public static void EmitJSEvent(this IReactContext reactContext, string eventEmitterName, string eventName, T1 arg1) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - }); - } - - public static void EmitJSEvent(this IReactContext reactContext, string eventEmitterName, string eventName, T1 arg1, T2 arg2) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - writer.WriteValue(arg2); - }); - } - - public static void EmitJSEvent(this IReactContext reactContext, string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - writer.WriteValue(arg2); - writer.WriteValue(arg3); - }); - } - - public static void EmitJSEvent(this IReactContext reactContext, - string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - writer.WriteValue(arg2); - writer.WriteValue(arg3); - writer.WriteValue(arg4); - }); - } - - public static void EmitJSEvent(this IReactContext reactContext, - string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - writer.WriteValue(arg2); - writer.WriteValue(arg3); - writer.WriteValue(arg4); - writer.WriteValue(arg5); - }); - } - - public static void EmitJSEvent(this IReactContext reactContext, - string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - writer.WriteValue(arg2); - writer.WriteValue(arg3); - writer.WriteValue(arg4); - writer.WriteValue(arg5); - writer.WriteValue(arg6); - }); - } - - public static void EmitJSEvent(this IReactContext reactContext, - string eventEmitterName, string eventName, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) - { - reactContext.EmitJSEvent(eventEmitterName, eventName, (IJSValueWriter writer) => - { - writer.WriteValue(arg1); - writer.WriteValue(arg2); - writer.WriteValue(arg3); - writer.WriteValue(arg4); - writer.WriteValue(arg5); - writer.WriteValue(arg6); - writer.WriteValue(arg7); - }); - } - } -} diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs index e9f5fd6767e..f2a7f3a094b 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactContextGenerator.cs @@ -11,14 +11,13 @@ namespace Microsoft.ReactNative.Managed { static class ReactContextGenerator { - private static MethodInfo GetExtensionMethod(string methodName, Type[] typeArgs, params Type[] requiredArgTypes) + private static MethodInfo GetMethod(string methodName, Type[] typeArgs, params Type[] requiredArgTypes) { var extMethod = - from member in typeof(ReactContextExtensions).GetMember(methodName, BindingFlags.Static | BindingFlags.Public) + from member in typeof(ReactContext).GetMember(methodName, BindingFlags.Instance | BindingFlags.Public) let method = member as MethodInfo let isGeneric = method.IsGenericMethod where method != null - && method.IsDefined(typeof(ExtensionAttribute), inherit: false) let parameters = method.GetParameters() where parameters.Length == typeArgs.Length + requiredArgTypes.Length && Enumerable.Range(0, requiredArgTypes.Length).All(i => parameters[i].ParameterType == requiredArgTypes[i]) @@ -26,22 +25,22 @@ private static MethodInfo GetExtensionMethod(string methodName, Type[] typeArgs, return extMethod.First(); } + public static ConstructorInfo ReactContextConstructor() => + typeof(ReactContext).GetConstructor(new Type[] { typeof(IReactContext) }); + public static MethodInfo DispatchEventOf(params Type[] typeArgs) { - return GetExtensionMethod(nameof(ReactContextExtensions.DispatchEvent), typeArgs, - typeof(IReactContext), typeof(FrameworkElement), typeof(string)); + return GetMethod(nameof(ReactContext.DispatchEvent), typeArgs, typeof(FrameworkElement), typeof(string)); } public static MethodInfo CallJSFunctionOf(params Type[] typeArgs) { - return GetExtensionMethod(nameof(ReactContextExtensions.CallJSFunction), typeArgs, - typeof(IReactContext), typeof(string), typeof(string)); + return GetMethod(nameof(ReactContext.CallJSFunction), typeArgs, typeof(string), typeof(string)); } public static MethodInfo EmitJSEventOf(params Type[] typeArgs) { - return GetExtensionMethod(nameof(ReactContextExtensions.EmitJSEvent), typeArgs, - typeof(IReactContext), typeof(string), typeof(string)); + return GetMethod(nameof(ReactContext.EmitJSEvent), typeArgs, typeof(string), typeof(string)); } } } diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactEventInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactEventInfo.cs index f73f2a57c53..858fc886069 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactEventInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactEventInfo.cs @@ -65,7 +65,8 @@ private ReactEventImpl MakeEvent(PropertyInfo propertyInfo, string eventEmitterN module.CastTo(propertyInfo.DeclaringType).SetProperty(propertyInfo, AutoLambda(propertyInfo.PropertyType, Parameters(eventArgTypes, out var args), - reactContext.CallExt(EmitJSEventOf(eventArgTypes), Constant(eventEmitterName), Constant(eventName), args)))); + New(ReactContextConstructor(), reactContext).Call( + EmitJSEventOf(eventArgTypes), Constant(eventEmitterName), Constant(eventName), args)))); } private ReactEventImpl MakeEvent(FieldInfo fieldInfo, string eventEmitterName, string eventName, Type[] eventArgTypes) @@ -84,7 +85,8 @@ private ReactEventImpl MakeEvent(FieldInfo fieldInfo, string eventEmitterName, s module.CastTo(fieldInfo.DeclaringType).SetField(fieldInfo, AutoLambda(fieldInfo.FieldType, Parameters(eventArgTypes, out var args), - reactContext.CallExt(EmitJSEventOf(eventArgTypes), Constant(eventEmitterName), Constant(eventName), args)))); + New(ReactContextConstructor(), reactContext).Call( + EmitJSEventOf(eventArgTypes), Constant(eventEmitterName), Constant(eventName), args)))); } public delegate void ReactEventImpl(object module, IReactContext reactContext); diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactFunctionInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactFunctionInfo.cs index faf617e684b..777ef64f0bf 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactFunctionInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactFunctionInfo.cs @@ -65,7 +65,8 @@ private ReactFunctionImpl MakeFunction(PropertyInfo propertyInfo, string moduleN module.CastTo(propertyInfo.DeclaringType).SetProperty(propertyInfo, AutoLambda(propertyInfo.PropertyType, Parameters(functionArgTypes, out var args), - reactContext.CallExt(CallJSFunctionOf(functionArgTypes), Constant(moduleName), Constant(functionName), args)))); + New(ReactContextConstructor(), reactContext).Call( + CallJSFunctionOf(functionArgTypes), Constant(moduleName), Constant(functionName), args)))); } private ReactFunctionImpl MakeFunction(FieldInfo fieldInfo, string moduleName, string functionName, Type[] functionArgTypes) @@ -84,7 +85,8 @@ private ReactFunctionImpl MakeFunction(FieldInfo fieldInfo, string moduleName, s module.CastTo(fieldInfo.DeclaringType).SetField(fieldInfo, AutoLambda(fieldInfo.FieldType, Parameters(functionArgTypes, out var args), - reactContext.CallExt(CallJSFunctionOf(functionArgTypes), Constant(moduleName), Constant(functionName), args)))); + New(ReactContextConstructor(), reactContext).Call( + CallJSFunctionOf(functionArgTypes), Constant(moduleName), Constant(functionName), args)))); } public delegate void ReactFunctionImpl(object module, IReactContext reactContext); diff --git a/vnext/Microsoft.ReactNative.SharedManaged/ReactInitializerInfo.cs b/vnext/Microsoft.ReactNative.SharedManaged/ReactInitializerInfo.cs index 7cb1a9aa062..9e8c23cd2c7 100644 --- a/vnext/Microsoft.ReactNative.SharedManaged/ReactInitializerInfo.cs +++ b/vnext/Microsoft.ReactNative.SharedManaged/ReactInitializerInfo.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Threading; using static Microsoft.ReactNative.Managed.JSValueGenerator; +using static Microsoft.ReactNative.Managed.ReactContextGenerator; using static System.Linq.Expressions.Expression; namespace Microsoft.ReactNative.Managed @@ -14,7 +15,7 @@ class ReactInitializerInfo public ReactInitializerInfo(MethodInfo methodInfo) { ParameterInfo[] parameters = methodInfo.GetParameters(); - if (parameters.Length != 1 || parameters[0].ParameterType != typeof(IReactContext)) + if (parameters.Length != 1 || parameters[0].ParameterType != typeof(ReactContext)) { throw new ArgumentException($"Initializer method must have one parameter of IReactContext type." + $" Module: {methodInfo.DeclaringType.FullName} Method: {methodInfo.Name}"); @@ -29,13 +30,13 @@ private ReactInitializerImpl MakeInitializer(MethodInfo methodInfo) // // (object module, IReactContext reactContext) => // { - // (module as MyModule).initializerMethod(reactContext); + // (module as MyModule).initializerMethod(new ReactContext(reactContext)); // }); return CompileLambda( Parameter(typeof(object), out var module), Parameter(typeof(IReactContext), out var reactContext), - Call(module.CastTo(methodInfo.DeclaringType), methodInfo, reactContext)); + Call(module.CastTo(methodInfo.DeclaringType), methodInfo, New(ReactContextConstructor(), reactContext))); } public delegate void ReactInitializerImpl(object module, IReactContext reactConext);