Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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"
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) =>
{
Expand Down
4 changes: 4 additions & 0 deletions vnext/Microsoft.ReactNative.Cxx/NativeModules.h
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,10 @@ struct ReactConstantProvider {
WriteProperty(m_writer, name, value);
}

IJSValueWriter const &Writer() const noexcept {
return m_writer;
}

private:
IJSValueWriter m_writer;
};
Expand Down
6 changes: 6 additions & 0 deletions vnext/Microsoft.ReactNative.Cxx/ReactContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <class... TArgs>
Expand Down Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -687,43 +687,48 @@ public void AddConstantProvider(Func<TModule, Action<ReactConstantProvider>> get
public void AddJSEvent(string eventEmitterName, string name, Action<TModule, 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<T1>(string eventEmitterName, string name, Action<TModule, Action<T1>> 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<T1, T2>(string eventEmitterName, string name, Action<TModule, Action<T1, T2>> 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<TModule, 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<T1>(string moduleName, string name, Action<TModule, Action<T1>> 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<T1, T2>(string moduleName, string name, Action<TModule, Action<T1, T2>> 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));
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
67 changes: 21 additions & 46 deletions vnext/Microsoft.ReactNative.SharedManaged/JSValueGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Expression> 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<Expression>();
ExpandArgArray(args, arguments);
return Expression.Call(AsExpression, method, args);
}

public MethodCallExpression CallExt(MethodInfo method, params object[] arguments)
{
var args = new List<Expression> { 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<Expression>();
ExpandArgArray(args, arguments);
return Expression.Invoke(AsExpression, args);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)AttributedViewManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)IJSValueTreeReader.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ReactContextExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ReactContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)IReactPromise.cs" />
<Compile Include="$(MSBuildThisFileDirectory)JSValue.cs" />
<Compile Include="$(MSBuildThisFileDirectory)JSValueGenerator.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>(string constantName, T value)
{
m_writer.WriteObjectProperty(constantName, value);
Writer.WriteObjectProperty(constantName, value);
}

private readonly IJSValueWriter m_writer;
}
}
Loading