* VM: Add support for CustomBubblingEventTypeConstants #3212
* VM: Add support for CustomDirectEventTypeConstants #3213
* Created IReactContext, which is passed in to the ViewManagerProvider delegate, to enable calling CallJSFunction and DispatchEvent from native code (partial #3208)
* VMs support "JS-style objects" for event params, property types (partial #3207, #3562)
This commit is contained in:
Jon Thysell 2019-11-25 16:09:23 -08:00 коммит произвёл GitHub
Родитель 45c209dd66
Коммит 531eef59be
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
27 изменённых файлов: 598 добавлений и 254 удалений

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "prerelease",
"comment": "View Manager Event Support",
"packageName": "react-native-windows",
"email": "jthysell@microsoft.com",
"commit": "a016d6d6709dcd01de300a1136756e36ba3b5070",
"date": "2019-11-25T20:09:28.093Z"
}

Просмотреть файл

@ -148,6 +148,16 @@ class SampleApp extends Component {
}
}
onLabelChangedCustomUserControlCS(evt) {
var label = evt.nativeEvent;
log(`SampleApp.onLabelChangedCustomUserControlCS("${label}")`);
}
onLabelChangedCustomUserControlCPP(evt) {
var label = evt.nativeEvent;
log(`SampleApp.onLabelChangedCustomUserControlCPP("${label}")`);
}
render() {
return (
<View style={styles.container}>
@ -161,10 +171,10 @@ class SampleApp extends Component {
<Button onPress={() => { this.onPressSampleModuleCS(); }} title="Call SampleModuleCS!" disabled={NativeModules.SampleModuleCS == null} />
<Button onPress={() => { this.onPressSampleModuleCPP(); }} title="Call SampleModuleCPP!" disabled={NativeModules.SampleModuleCPP == null} />
<CustomUserControlCS style={styles.customcontrol} label="CustomUserControlCS!" ref={(ref) => { this._CustomUserControlCSRef = ref; }} />
<CustomUserControlCS style={styles.customcontrol} label="CustomUserControlCS!" ref={(ref) => { this._CustomUserControlCSRef = ref; }} onLabelChanged={(evt) => { this.onLabelChangedCustomUserControlCS(evt); }} />
<Button onPress={() => { this.onPressCustomUserControlCS(); }} title="Call CustomUserControlCS Commands!" />
<CustomUserControlCPP style={styles.customcontrol} label="CustomUserControlCPP!" ref={(ref) => { this._CustomUserControlCPPRef = ref; }} />
<CustomUserControlCPP style={styles.customcontrol} label="CustomUserControlCPP!" ref={(ref) => { this._CustomUserControlCPPRef = ref; }} onLabelChanged={(evt) => { this.onLabelChangedCustomUserControlCPP(evt); }} />
<Button onPress={() => { this.onPressCustomUserControlCPP(); }} title="Call CustomUserControlCPP Commands!" />
<Text style={styles.instructions}>

Просмотреть файл

@ -18,13 +18,31 @@ using namespace Windows::UI::Xaml::Controls;
namespace winrt::SampleLibraryCPP::implementation {
CustomUserControlViewManagerCPP::CustomUserControlViewManagerCPP(IReactContext const &reactContext)
: m_reactContext{reactContext} {}
IReactContext CustomUserControlViewManagerCPP::ReactContext() noexcept {
return m_reactContext;
}
// IViewManager
hstring CustomUserControlViewManagerCPP::Name() noexcept {
return L"CustomUserControlCPP";
}
FrameworkElement CustomUserControlViewManagerCPP::CreateView() noexcept {
return winrt::SampleLibraryCPP::CustomUserControlCPP();
auto const &view = winrt::SampleLibraryCPP::CustomUserControlCPP();
view.RegisterPropertyChangedCallback(
winrt::SampleLibraryCPP::CustomUserControlCPP::LabelProperty(),
[this](
winrt::Windows::UI::Xaml::DependencyObject obj, winrt::Windows::UI::Xaml::DependencyProperty prop) noexcept {
if (auto c = obj.try_as<winrt::SampleLibraryCPP::CustomUserControlCPP>()) {
ReactContext().DispatchEvent(c, L"topLabelChanged", box_value(c.Label()));
}
});
return view;
}
// IViewManagerWithNativeProperties
@ -92,4 +110,21 @@ void CustomUserControlViewManagerCPP::DispatchCommand(
}
}
// IViewManagerWithExportedEventTypeConstants
IMapView<hstring, IInspectable> CustomUserControlViewManagerCPP::ExportedCustomBubblingEventTypeConstants() noexcept {
auto constants = winrt::single_threaded_map<hstring, IInspectable>();
return constants.GetView();
}
IMapView<hstring, IInspectable> CustomUserControlViewManagerCPP::ExportedCustomDirectEventTypeConstants() noexcept {
auto constants = winrt::single_threaded_map<hstring, IInspectable>();
auto registration = winrt::single_threaded_map<hstring, IInspectable>();
registration.Insert(L"registrationName", box_value(L"onLabelChanged"));
constants.Insert(L"topLabelChanged", registration.GetView());
return constants.GetView();
}
} // namespace winrt::SampleLibraryCPP::implementation

Просмотреть файл

@ -7,17 +7,21 @@
namespace winrt::SampleLibraryCPP::implementation {
struct CustomUserControlViewManagerCPP : winrt::implements<
CustomUserControlViewManagerCPP,
winrt::Microsoft::ReactNative::Bridge::IViewManager,
winrt::Microsoft::ReactNative::Bridge::IViewManagerWithNativeProperties,
winrt::Microsoft::ReactNative::Bridge::IViewManagerWithCommands> {
struct CustomUserControlViewManagerCPP
: winrt::implements<
CustomUserControlViewManagerCPP,
winrt::Microsoft::ReactNative::Bridge::IViewManager,
winrt::Microsoft::ReactNative::Bridge::IViewManagerWithNativeProperties,
winrt::Microsoft::ReactNative::Bridge::IViewManagerWithCommands,
winrt::Microsoft::ReactNative::Bridge::IViewManagerWithExportedEventTypeConstants> {
public:
CustomUserControlViewManagerCPP() = default;
CustomUserControlViewManagerCPP(winrt::Microsoft::ReactNative::Bridge::IReactContext const &reactContext);
// IViewManager
winrt::hstring Name() noexcept;
winrt::Microsoft::ReactNative::Bridge::IReactContext ReactContext() noexcept;
winrt::Windows::UI::Xaml::FrameworkElement CreateView() noexcept;
// IViewManagerWithNativeProperties
@ -38,6 +42,16 @@ struct CustomUserControlViewManagerCPP : winrt::implements<
int64_t commandId,
winrt::Windows::Foundation::Collections::IVectorView<winrt::Windows::Foundation::IInspectable>
commandArgs) noexcept;
// IViewManagerWithExportedEventTypeConstants
winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, winrt::Windows::Foundation::IInspectable>
ExportedCustomBubblingEventTypeConstants() noexcept;
winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, winrt::Windows::Foundation::IInspectable>
ExportedCustomDirectEventTypeConstants() noexcept;
private:
winrt::Microsoft::ReactNative::Bridge::IReactContext m_reactContext{nullptr};
};
} // namespace winrt::SampleLibraryCPP::implementation

Просмотреть файл

@ -17,8 +17,9 @@ namespace winrt::SampleLibraryCPP::implementation {
void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept {
AddAttributedModules(packageBuilder);
packageBuilder.AddViewManager(
L"CustomUserControlViewManagerCPP", []() { return winrt::make<CustomUserControlViewManagerCPP>(); });
packageBuilder.AddViewManager(L"CustomUserControlViewManagerCPP", [](IReactContext const &reactContext) {
return winrt::make<CustomUserControlViewManagerCPP>(reactContext);
});
}
} // namespace winrt::SampleLibraryCPP::implementation

Просмотреть файл

@ -1,16 +1,35 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Diagnostics;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Controls;
using Microsoft.ReactNative.Managed;
using Microsoft.ReactNative.Bridge;
using Windows.UI.Xaml;
namespace SampleLibraryCS
{
internal class CustomUserControlViewManagerCS : AttributedViewManager<CustomUserControlCS>
{
public CustomUserControlViewManagerCS(IReactContext reactContext) : base(reactContext) { }
public override FrameworkElement CreateView()
{
var view = new CustomUserControlCS();
view.RegisterPropertyChangedCallback(CustomUserControlCS.LabelProperty, (obj, prop) =>
{
if (obj is CustomUserControlCS c)
{
LabelChanged(c, c.Label);
}
});
return view;
}
[ViewManagerProperty("label")]
public void SetLabel(CustomUserControlCS view, string value)
{
@ -55,5 +74,8 @@ namespace SampleLibraryCS
{
Debug.WriteLine($"{Name}.{nameof(CustomCommand)}({view.Tag}, \"{arg}\")");
}
[ViewManagerExportedDirectEventTypeConstant]
public ViewManagerEvent<CustomUserControlCS, string> LabelChanged;
}
}

Просмотреть файл

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
@ -11,23 +12,66 @@ using Microsoft.ReactNative.Bridge;
namespace Microsoft.ReactNative.Managed
{
internal abstract class AttributedViewManager<T> :
internal abstract class AttributedViewManager<TFrameworkElement> :
IViewManager,
IViewManagerWithExportedViewConstants,
IViewManagerWithNativeProperties,
IViewManagerWithCommands
where T : FrameworkElement, new()
IViewManagerWithCommands,
IViewManagerWithExportedEventTypeConstants
where TFrameworkElement : FrameworkElement, new()
{
public virtual string Name => typeof(T).Name;
public IReactContext ReactContext { get; private set; }
public virtual FrameworkElement CreateView() => new T();
protected AttributedViewManager(IReactContext reactContext)
{
ReactContext = reactContext;
}
public IReadOnlyDictionary<string, object> ExportedViewConstants => _exportedViewConstants ?? (_exportedViewConstants = GetConstantsByAttribute<ViewManagerExportedViewConstantAttribute>());
#region IViewManager
public virtual string Name => typeof(TFrameworkElement).Name;
public virtual FrameworkElement CreateView() => new TFrameworkElement();
#endregion
#region Constants
public virtual IReadOnlyDictionary<string, object> ExportedViewConstants => _exportedViewConstants ?? (_exportedViewConstants = GetExportedViewConstants());
private IReadOnlyDictionary<string, object> _exportedViewConstants;
private IReadOnlyDictionary<string, object> GetExportedViewConstants()
{
var typeInfo = GetType().GetTypeInfo();
var constants = new Dictionary<string, object>();
foreach (var fieldInfo in typeInfo.DeclaredFields)
{
var attribute = fieldInfo.GetCustomAttribute<ViewManagerExportedViewConstantAttribute>();
if (null != attribute)
{
constants.Add(attribute.ConstantName ?? fieldInfo.Name, fieldInfo.GetValue(this));
}
}
foreach (var propertyInfo in typeInfo.DeclaredProperties)
{
var attribute = propertyInfo.GetCustomAttribute<ViewManagerExportedViewConstantAttribute>();
if (null != attribute)
{
constants.Add(attribute.ConstantName ?? propertyInfo.Name, propertyInfo.GetMethod.Invoke(this, null));
}
}
return constants;
}
#endregion
#region Properties
public IReadOnlyDictionary<string, ViewManagerPropertyType> NativeProps
public virtual IReadOnlyDictionary<string, ViewManagerPropertyType> NativeProps
{
get
{
@ -47,22 +91,40 @@ namespace Microsoft.ReactNative.Managed
}
private IReadOnlyDictionary<string, ViewManagerPropertyType> _nativeProps;
internal Dictionary<string, ViewManagerProperty<T>> ViewManagerProperties
public virtual void UpdateProperties(FrameworkElement view, IReadOnlyDictionary<string, object> propertyMap)
{
if (view is TFrameworkElement viewAsT)
{
foreach (var property in propertyMap)
{
if (ViewManagerProperties.TryGetValue(property.Key, out ViewManagerProperty<TFrameworkElement> setter))
{
setter.Setter(viewAsT, property.Value);
}
}
}
else
{
throw new ArgumentOutOfRangeException(nameof(view));
}
}
internal Dictionary<string, ViewManagerProperty<TFrameworkElement>> ViewManagerProperties
{
get
{
if (null == _properties)
{
var properties = new Dictionary<string, ViewManagerProperty<T>>();
var properties = new Dictionary<string, ViewManagerProperty<TFrameworkElement>>();
foreach (var methodInfo in GetType().GetTypeInfo().DeclaredMethods)
{
var propertyAttribute = methodInfo.GetCustomAttribute<ViewManagerPropertyAttribute>();
if (null != propertyAttribute)
{
var setter = new ViewManagerProperty<T>();
setter.Name = propertyAttribute.Name ?? methodInfo.Name;
setter.Type = propertyAttribute.Type ?? TypeToViewManagerPropertyType(methodInfo.GetParameters()[1].ParameterType);
var setter = new ViewManagerProperty<TFrameworkElement>();
setter.Name = propertyAttribute.PropertyName ?? methodInfo.Name;
setter.Type = propertyAttribute.PropertyType ?? TypeToViewManagerPropertyType(methodInfo.GetParameters()[1].ParameterType);
setter.Setter = MakePropertySetterMethod(methodInfo);
properties.Add(setter.Name, setter);
@ -75,33 +137,31 @@ namespace Microsoft.ReactNative.Managed
return _properties;
}
}
private Dictionary<string, ViewManagerProperty<T>> _properties;
private Dictionary<string, ViewManagerProperty<TFrameworkElement>> _properties;
public void UpdateProperties(FrameworkElement view, IReadOnlyDictionary<string, object> propertyMap)
{
if (view is T viewAsT)
{
foreach (var property in propertyMap)
{
if (ViewManagerProperties.TryGetValue(property.Key, out ViewManagerProperty<T> setter))
{
setter.Setter(viewAsT, property.Value);
}
}
}
else
{
throw new ArgumentOutOfRangeException(nameof(view));
}
}
internal struct ViewManagerProperty<U> where U : T
internal struct ViewManagerProperty<U> where U : TFrameworkElement
{
public string Name;
public ViewManagerPropertyType Type;
public Action<U, object> Setter;
}
private Action<TFrameworkElement, object> MakePropertySetterMethod(MethodInfo methodInfo)
{
var parameters = methodInfo.GetParameters();
if (parameters.Length == 2
&& parameters[0].ParameterType == typeof(TFrameworkElement))
{
return (view, propertyValue) =>
{
methodInfo.Invoke(this, new object[] { view, propertyValue });
};
}
throw new ArgumentException($"Unable to parse parameters for {methodInfo.Name}.");
}
private static ViewManagerPropertyType TypeToViewManagerPropertyType(Type t)
{
if (t == typeof(bool) || t == typeof(bool?))
@ -112,7 +172,7 @@ namespace Microsoft.ReactNative.Managed
{
return ViewManagerPropertyType.String;
}
else if (t == typeof(decimal) || t == typeof(double) || t == typeof(float) || t == typeof(long) || t == typeof(int) || t== typeof(short) || t == typeof(sbyte) || t == typeof(ulong) || t == typeof(uint) || t == typeof(ushort) || t == typeof(byte) ||
else if (t == typeof(decimal) || t == typeof(double) || t == typeof(float) || t == typeof(long) || t == typeof(int) || t == typeof(short) || t == typeof(sbyte) || t == typeof(ulong) || t == typeof(uint) || t == typeof(ushort) || t == typeof(byte) ||
t == typeof(decimal?) || t == typeof(double?) || t == typeof(float?) || t == typeof(long?) || t == typeof(int?) || t == typeof(sbyte?) || t == typeof(ulong?) || t == typeof(uint?) || t == typeof(ushort?) || t == typeof(byte?))
{
return ViewManagerPropertyType.Number;
@ -137,7 +197,7 @@ namespace Microsoft.ReactNative.Managed
#region Commands
public IReadOnlyDictionary<string, long> Commands
public virtual IReadOnlyDictionary<string, long> Commands
{
get
{
@ -157,39 +217,11 @@ namespace Microsoft.ReactNative.Managed
}
private IReadOnlyDictionary<string, long> _commands;
internal Dictionary<long, ViewManagerCommand<T>> ViewManagerCommands
public virtual void DispatchCommand(FrameworkElement view, long commandId, IReadOnlyList<object> commandArgs)
{
get
if (view is TFrameworkElement viewAsT)
{
if (null == _viewManagerCommands)
{
var viewManagerCommands = new Dictionary<long, ViewManagerCommand<T>>();
foreach (var methodInfo in GetType().GetTypeInfo().DeclaredMethods)
{
var commandAttribute = methodInfo.GetCustomAttribute<ViewManagerCommandAttribute>();
if (null != commandAttribute)
{
var command = new ViewManagerCommand<T>();
command.CommandName = commandAttribute.Name ?? methodInfo.Name;
command.CommandId = commandAttribute.CommandId ?? viewManagerCommands.Count;
command.CommandMethod = MakeCommandMethod(methodInfo);
viewManagerCommands.Add(command.CommandId, command);
}
}
_viewManagerCommands = viewManagerCommands;
}
return _viewManagerCommands;
}
}
private Dictionary<long, ViewManagerCommand<T>> _viewManagerCommands;
public void DispatchCommand(FrameworkElement view, long commandId, IReadOnlyList<object> commandArgs)
{
if (view is T viewAsT)
{
if (ViewManagerCommands.TryGetValue(commandId, out ViewManagerCommand<T> command))
if (ViewManagerCommands.TryGetValue(commandId, out ViewManagerCommand<TFrameworkElement> command))
{
command.CommandMethod(viewAsT, commandArgs);
}
@ -200,38 +232,46 @@ namespace Microsoft.ReactNative.Managed
}
}
internal struct ViewManagerCommand<U> where U : T
internal Dictionary<long, ViewManagerCommand<TFrameworkElement>> ViewManagerCommands
{
get
{
if (null == _viewManagerCommands)
{
var viewManagerCommands = new Dictionary<long, ViewManagerCommand<TFrameworkElement>>();
foreach (var methodInfo in GetType().GetTypeInfo().DeclaredMethods)
{
var commandAttribute = methodInfo.GetCustomAttribute<ViewManagerCommandAttribute>();
if (null != commandAttribute)
{
var command = new ViewManagerCommand<TFrameworkElement>();
command.CommandName = commandAttribute.CommandName ?? methodInfo.Name;
command.CommandId = viewManagerCommands.Count;
command.CommandMethod = MakeCommandMethod(methodInfo);
viewManagerCommands.Add(command.CommandId, command);
}
}
_viewManagerCommands = viewManagerCommands;
}
return _viewManagerCommands;
}
}
private Dictionary<long, ViewManagerCommand<TFrameworkElement>> _viewManagerCommands;
internal struct ViewManagerCommand<U> where U : TFrameworkElement
{
public string CommandName;
public long CommandId;
public Action<U, IReadOnlyList<object>> CommandMethod;
}
#endregion
#region Reflection Helpers
private Action<T, object> MakePropertySetterMethod(MethodInfo methodInfo)
{
var parameters = methodInfo.GetParameters();
if (parameters.Length == 2
&& parameters[0].ParameterType == typeof(T))
{
return (view, propertyValue) =>
{
methodInfo.Invoke(this, new object[] { view, propertyValue });
};
}
throw new ArgumentException($"Unable to parse parameters for {methodInfo.Name}.");
}
private Action<T, IReadOnlyList<object>> MakeCommandMethod(MethodInfo methodInfo)
private Action<TFrameworkElement, IReadOnlyList<object>> MakeCommandMethod(MethodInfo methodInfo)
{
var parameters = methodInfo.GetParameters();
if (parameters.Length == 2
&& parameters[0].ParameterType == typeof(T)
&& parameters[0].ParameterType == typeof(TFrameworkElement)
&& parameters[1].ParameterType == typeof(IReadOnlyList<object>))
{
return (view, commandArgs) =>
@ -240,7 +280,7 @@ namespace Microsoft.ReactNative.Managed
};
}
else if (parameters.Length >= 2
&& parameters[0].ParameterType == typeof(T))
&& parameters[0].ParameterType == typeof(TFrameworkElement))
{
return (view, commandArgs) =>
{
@ -255,7 +295,17 @@ namespace Microsoft.ReactNative.Managed
throw new ArgumentException($"Unable to parse parameters for {methodInfo.Name}.");
}
private IReadOnlyDictionary<string, object> GetConstantsByAttribute<U>() where U : ViewManagerNamedAttribute
#endregion
#region Events
public virtual IReadOnlyDictionary<string, object> ExportedCustomBubblingEventTypeConstants => _exportedCustomBubblingEventTypeConstants ?? (_exportedCustomBubblingEventTypeConstants = GetExportedCustomBubblingEventTypeConstants());
private IReadOnlyDictionary<string, object> _exportedCustomBubblingEventTypeConstants;
public virtual IReadOnlyDictionary<string, object> ExportedCustomDirectEventTypeConstants => _exportedCustomDirectEventTypeConstants ?? (_exportedCustomDirectEventTypeConstants = GetExportedDirectEventTypeConstants());
private IReadOnlyDictionary<string, object> _exportedCustomDirectEventTypeConstants;
private IReadOnlyDictionary<string, object> GetExportedCustomBubblingEventTypeConstants()
{
var typeInfo = GetType().GetTypeInfo();
@ -263,25 +313,151 @@ namespace Microsoft.ReactNative.Managed
foreach (var fieldInfo in typeInfo.DeclaredFields)
{
var attribute = fieldInfo.GetCustomAttribute<U>();
if (null != attribute)
var attribute = fieldInfo.GetCustomAttribute<ViewManagerExportedBubblingEventTypeConstantAttribute>();
if (TryMakeBubblingEvent(attribute, fieldInfo, fieldInfo.FieldType, out string key, out object value, out Delegate memberValue))
{
constants.Add(attribute.Name ?? fieldInfo.Name, fieldInfo.GetValue(this));
constants.Add(key, value);
fieldInfo.SetValue(this, memberValue);
}
}
foreach (var propertyInfo in typeInfo.DeclaredProperties)
{
var attribute = propertyInfo.GetCustomAttribute<U>();
if (null != attribute)
var attribute = propertyInfo.GetCustomAttribute<ViewManagerExportedBubblingEventTypeConstantAttribute>();
if (TryMakeBubblingEvent(attribute, propertyInfo, propertyInfo.PropertyType, out string key, out object value, out Delegate memberValue))
{
constants.Add(attribute.Name ?? propertyInfo.Name, propertyInfo.GetMethod.Invoke(this, null));
constants.Add(key, value);
propertyInfo.SetValue(this, memberValue);
}
}
return constants;
}
private bool TryMakeBubblingEvent(ViewManagerExportedBubblingEventTypeConstantAttribute attribute, MemberInfo memberInfo, Type memberType, out string constantKey, out object constantValue, out Delegate memberValue)
{
if (null != attribute && null != memberInfo && TryGetEventDataType(memberType, out Type eventDataType))
{
var eventName = attribute.EventName ?? "top" + memberInfo.Name;
var bubbleName = attribute.BubbleCallbackName ?? "on" + memberInfo.Name;
var captureName = attribute.CaptureCallbackName ?? bubbleName + "Capture";
var registration = new Dictionary<string, object>
{
{ "phasedRegistrationNames", new Dictionary<string, object>()
{
{ "bubbled", bubbleName },
{ "captured", captureName },
}
}
};
constantKey = eventName;
constantValue = registration;
memberValue = MakeEventDelegate(eventName, memberType, eventDataType);
return true;
}
constantKey = default;
constantValue = default;
memberValue = default;
return false;
}
private IReadOnlyDictionary<string, object> GetExportedDirectEventTypeConstants()
{
var typeInfo = GetType().GetTypeInfo();
var constants = new Dictionary<string, object>();
foreach (var fieldInfo in typeInfo.DeclaredFields)
{
var attribute = fieldInfo.GetCustomAttribute<ViewManagerExportedDirectEventTypeConstantAttribute>();
if (TryMakeDirectEvent(attribute, fieldInfo, fieldInfo.FieldType, out string key, out object value, out Delegate memberValue))
{
constants.Add(key, value);
fieldInfo.SetValue(this, memberValue);
}
}
foreach (var propertyInfo in typeInfo.DeclaredProperties)
{
var attribute = propertyInfo.GetCustomAttribute<ViewManagerExportedDirectEventTypeConstantAttribute>();
if (TryMakeDirectEvent(attribute, propertyInfo, propertyInfo.PropertyType, out string key, out object value, out Delegate memberValue))
{
constants.Add(key, value);
propertyInfo.SetValue(this, memberValue);
}
}
return constants;
}
private bool TryMakeDirectEvent(ViewManagerExportedDirectEventTypeConstantAttribute attribute, MemberInfo memberInfo, Type memberType, out string constantKey, out object constantValue, out Delegate memberValue)
{
if (null != attribute && null != memberInfo && TryGetEventDataType(memberType, out Type eventDataType))
{
var eventName = attribute.EventName ?? "top" + memberInfo.Name;
var callbackName = attribute.CallbackName ?? "on" + memberInfo.Name;
var registration = new Dictionary<string, object>
{
{ "registrationName", callbackName }
};
constantKey = eventName;
constantValue = registration;
memberValue = MakeEventDelegate(eventName, memberType, eventDataType);
return true;
}
constantKey = default;
constantValue = default;
memberValue = default;
return false;
}
private bool TryGetEventDataType(Type eventType, out Type eventDataType)
{
if (null != eventType && typeof(Delegate).IsAssignableFrom(eventType))
{
var eventDelegateMethod = eventType.GetMethod("Invoke");
ParameterInfo[] parameters = eventDelegateMethod.GetParameters();
if (parameters.Length == 2 && parameters[0].ParameterType == typeof(TFrameworkElement))
{
eventDataType = parameters[1].ParameterType;
return true;
}
}
eventDataType = default;
return false;
}
private Delegate MakeEventDelegate(string eventName, Type memberType, Type eventDataType)
{
//
// (TFrameworkElement view, TEventData eventData) =>
// {
// ReactContext.DispatchEvent(view, eventName, eventData);
// };
//
ParameterExpression viewParameter = Expression.Parameter(typeof(TFrameworkElement), "view");
ParameterExpression eventDataParameter = Expression.Parameter(eventDataType, "eventData");
MemberExpression thisReactContext = Expression.Property(Expression.Constant(this), "ReactContext");
MethodCallExpression body = Expression.Call(thisReactContext, typeof(IReactContext).GetMethod("DispatchEvent"), viewParameter, Expression.Constant(eventName, typeof(string)), eventDataParameter);
return Expression.Lambda(memberType, body, viewParameter, eventDataParameter).Compile();
}
#endregion
}
}

Просмотреть файл

@ -27,5 +27,6 @@
<Compile Include="$(MSBuildThisFileDirectory)ReactPackageBuilderExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ReactSyncMethodInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewManagerAttributes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ViewManagerEvent.cs" />
</ItemGroup>
</Project>

Просмотреть файл

@ -30,7 +30,14 @@ namespace Microsoft.ReactNative.Managed
{
if (!typeInfo.IsAbstract && typeInfo.ImplementedInterfaces.Contains(typeof(IViewManager)))
{
packageBuilder.AddViewManager(typeInfo.Name, () => (IViewManager)Activator.CreateInstance(typeInfo.AsType()));
if (typeInfo.DeclaredConstructors.Any(cInfo => cInfo.GetParameters().Length == 1 && cInfo.GetParameters()[0].ParameterType == typeof(IReactContext)))
{
packageBuilder.AddViewManager(typeInfo.Name, (reactContext) => (IViewManager)Activator.CreateInstance(typeInfo.AsType(), reactContext));
}
else if (typeInfo.DeclaredConstructors.Any(cInfo => cInfo.GetParameters().Length == 0))
{
packageBuilder.AddViewManager(typeInfo.Name, (reactContext) => (IViewManager)Activator.CreateInstance(typeInfo.AsType()));
}
}
}
}

Просмотреть файл

@ -7,54 +7,87 @@ using Microsoft.ReactNative.Bridge;
namespace Microsoft.ReactNative.Managed
{
internal abstract class ViewManagerNamedAttribute : Attribute
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
internal class ViewManagerExportedViewConstantAttribute : Attribute
{
public string Name { get; set; }
public string ConstantName { get; set; }
public ViewManagerNamedAttribute() : base() { }
public ViewManagerExportedViewConstantAttribute() : base() { }
public ViewManagerNamedAttribute(string name)
public ViewManagerExportedViewConstantAttribute(string constantName)
{
Name = name ?? throw new ArgumentNullException(nameof(name));
ConstantName = constantName ?? throw new ArgumentNullException(nameof(constantName));
}
}
[AttributeUsage(AttributeTargets.Method)]
internal class ViewManagerPropertyAttribute : Attribute
{
public string PropertyName { get; set; }
public ViewManagerPropertyType? PropertyType { get; set; } = null;
public ViewManagerPropertyAttribute() : base() { }
public ViewManagerPropertyAttribute(string propertyName)
{
PropertyName = propertyName ?? throw new ArgumentNullException(nameof(propertyName));
}
public ViewManagerPropertyAttribute(string propertyName, ViewManagerPropertyType type) : this(propertyName)
{
PropertyType = type;
}
}
[AttributeUsage(AttributeTargets.Method)]
internal class ViewManagerCommandAttribute : Attribute
{
public string CommandName { get; set; }
public ViewManagerCommandAttribute() : base() { }
public ViewManagerCommandAttribute(string commandName)
{
CommandName = commandName ?? throw new ArgumentNullException(nameof(commandName));
}
}
internal class ViewManagerExportedDirectEventTypeConstantAttribute : Attribute
{
public string EventName { get; private set; }
public string CallbackName { get; private set; }
public ViewManagerExportedDirectEventTypeConstantAttribute() : base() { }
public ViewManagerExportedDirectEventTypeConstantAttribute(string eventName, string callbackName)
{
EventName = eventName ?? throw new ArgumentNullException(nameof(eventName));
CallbackName = callbackName ?? throw new ArgumentNullException(nameof(callbackName));
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
internal class ViewManagerExportedViewConstantAttribute : ViewManagerNamedAttribute
internal class ViewManagerExportedBubblingEventTypeConstantAttribute : Attribute
{
public ViewManagerExportedViewConstantAttribute() : base() { }
public string EventName { get; private set; }
public ViewManagerExportedViewConstantAttribute(string name) : base(name) { }
}
public string BubbleCallbackName { get; private set; }
[AttributeUsage(AttributeTargets.Method)]
internal class ViewManagerPropertyAttribute : ViewManagerNamedAttribute
{
public ViewManagerPropertyType? Type { get; set; } = null;
public string CaptureCallbackName { get; private set; }
public ViewManagerPropertyAttribute() : base() { }
public ViewManagerExportedBubblingEventTypeConstantAttribute() : base() { }
public ViewManagerPropertyAttribute(string name) : base(name) { }
public ViewManagerPropertyAttribute(string name, ViewManagerPropertyType type) : this(name)
public ViewManagerExportedBubblingEventTypeConstantAttribute(string eventName, string bubbleCallbackName)
{
Type = type;
EventName = eventName ?? throw new ArgumentNullException(nameof(eventName));
BubbleCallbackName = bubbleCallbackName ?? throw new ArgumentNullException(nameof(bubbleCallbackName));
}
}
[AttributeUsage(AttributeTargets.Method)]
internal class ViewManagerCommandAttribute : ViewManagerNamedAttribute
{
public long? CommandId { get; set; }
public ViewManagerCommandAttribute() : base() { }
public ViewManagerCommandAttribute(string name) : base(name) { }
public ViewManagerCommandAttribute(string name, long commandId) : this(name)
public ViewManagerExportedBubblingEventTypeConstantAttribute(string eventName, string bubbleCallbackName, string captureCallbackName) : this(eventName, bubbleCallbackName)
{
CommandId = commandId;
CaptureCallbackName = captureCallbackName ?? throw new ArgumentNullException(nameof(captureCallbackName));
}
}
}

Просмотреть файл

@ -0,0 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using Windows.UI.Xaml;
namespace Microsoft.ReactNative.Managed
{
internal delegate void ViewManagerEvent<TFrameworkElement, TEventData>(TFrameworkElement view, TEventData eventData) where TFrameworkElement : FrameworkElement;
}

Просмотреть файл

@ -17,6 +17,7 @@ ABIViewManager::ABIViewManager(
m_viewManagerWithExportedViewConstants{viewManager.try_as<IViewManagerWithExportedViewConstants>()},
m_viewManagerWithNativeProperties{viewManager.try_as<IViewManagerWithNativeProperties>()},
m_viewManagerWithCommands{viewManager.try_as<IViewManagerWithCommands>()},
m_viewManagerWithExportedEventTypeConstants{viewManager.try_as<IViewManagerWithExportedEventTypeConstants>()},
m_name{to_string(viewManager.Name())} {
if (m_viewManagerWithNativeProperties) {
m_nativeProps = m_viewManagerWithNativeProperties.NativeProps();
@ -151,4 +152,34 @@ void ABIViewManager::DispatchCommand(
}
}
folly::dynamic ABIViewManager::GetExportedCustomBubblingEventTypeConstants() const {
folly::dynamic parent = Super::GetExportedCustomBubblingEventTypeConstants();
if (m_viewManagerWithExportedEventTypeConstants) {
auto outerChild = m_viewManagerWithExportedEventTypeConstants.ExportedCustomBubblingEventTypeConstants();
for (const auto &pair : outerChild) {
std::string key = to_string(pair.Key());
folly::dynamic value = ConvertToDynamic(pair.Value());
parent.insert(key, value);
}
}
return parent;
}
folly::dynamic ABIViewManager::GetExportedCustomDirectEventTypeConstants() const {
folly::dynamic parent = Super::GetExportedCustomDirectEventTypeConstants();
if (m_viewManagerWithExportedEventTypeConstants) {
auto outerChild = m_viewManagerWithExportedEventTypeConstants.ExportedCustomDirectEventTypeConstants();
for (const auto &pair : outerChild) {
std::string key = to_string(pair.Key());
folly::dynamic value = ConvertToDynamic(pair.Value());
parent.insert(key, value);
}
}
return parent;
}
} // namespace winrt::Microsoft::ReactNative::Bridge

Просмотреть файл

@ -43,6 +43,10 @@ class ABIViewManager : public react::uwp::FrameworkElementViewManager {
int64_t commandId,
const folly::dynamic &commandArgs) override;
folly::dynamic GetExportedCustomBubblingEventTypeConstants() const override;
folly::dynamic GetExportedCustomDirectEventTypeConstants() const override;
protected:
winrt::Windows::UI::Xaml::DependencyObject CreateViewCore(int64_t) override;
@ -51,6 +55,8 @@ class ABIViewManager : public react::uwp::FrameworkElementViewManager {
winrt::Microsoft::ReactNative::Bridge::IViewManagerWithExportedViewConstants m_viewManagerWithExportedViewConstants;
winrt::Microsoft::ReactNative::Bridge::IViewManagerWithNativeProperties m_viewManagerWithNativeProperties;
winrt::Microsoft::ReactNative::Bridge::IViewManagerWithCommands m_viewManagerWithCommands;
winrt::Microsoft::ReactNative::Bridge::IViewManagerWithExportedEventTypeConstants
m_viewManagerWithExportedEventTypeConstants;
winrt::Windows::Foundation::Collections::IMapView<winrt::hstring, ViewManagerPropertyType> m_nativeProps;
};

Просмотреть файл

@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "IReactContext.h"
#include "ReactSupport.h"
namespace winrt::Microsoft::ReactNative::Bridge {
void ReactContext::DispatchEvent(
winrt::Windows::UI::Xaml::FrameworkElement const &view,
hstring const &eventName,
IInspectable const &eventData) noexcept {
if (auto instance = m_instance.lock()) {
instance->DispatchEvent(unbox_value<int64_t>(view.Tag()), to_string(eventName), ConvertToDynamic(eventData));
}
}
void ReactContext::CallJsFunction(
hstring const &moduleName,
hstring const &method,
IInspectable const &params) noexcept {
if (auto instance = m_instance.lock()) {
instance->CallJsFunction(to_string(moduleName), to_string(method), ConvertToDynamic(params));
}
}
} // namespace winrt::Microsoft::ReactNative::Bridge

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include <ReactUWP/IReactInstance.h>
#include "winrt/Microsoft.ReactNative.Bridge.h"
namespace winrt::Microsoft::ReactNative::Bridge {
struct ReactContext : winrt::implements<ReactContext, IReactContext> {
ReactContext(std::weak_ptr<react::uwp::IReactInstance> instance) noexcept : m_instance(instance) {}
public: // IReactContext
void DispatchEvent(
winrt::Windows::UI::Xaml::FrameworkElement const &view,
hstring const &eventName,
IInspectable const &eventData) noexcept;
void CallJsFunction(hstring const &moduleName, hstring const &method, IInspectable const &params) noexcept;
private:
std::weak_ptr<react::uwp::IReactInstance> m_instance;
};
} // namespace winrt::Microsoft::ReactNative::Bridge

Просмотреть файл

@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
namespace Microsoft.ReactNative.Bridge
{
[webhosthidden]
interface IReactContext
{
void DispatchEvent(Windows.UI.Xaml.FrameworkElement view, String eventName, IInspectable eventData);
void CallJsFunction(String moduleName, String method, IInspectable params);
};
}

Просмотреть файл

@ -1,13 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import "IReactContext.idl";
import "IReactModuleBuilder.idl";
import "IViewManager.idl";
namespace Microsoft.ReactNative.Bridge {
delegate Object ReactModuleProvider(IReactModuleBuilder moduleBuilder);
delegate IViewManager ReactViewManagerProvider();
delegate IViewManager ReactViewManagerProvider(IReactContext reactContext);
interface IReactPackageBuilder {
// TODO: Add message thread argument

Просмотреть файл

@ -43,4 +43,12 @@ namespace Microsoft.ReactNative.Bridge
void DispatchCommand(Windows.UI.Xaml.FrameworkElement view, Int64 commandId, Windows.Foundation.Collections.IVectorView<IInspectable> commandArgs);
};
[webhosthidden]
interface IViewManagerWithExportedEventTypeConstants
{
Windows.Foundation.Collections.IMapView<String, IInspectable> ExportedCustomBubblingEventTypeConstants { get; };
Windows.Foundation.Collections.IMapView<String, IInspectable> ExportedCustomDirectEventTypeConstants { get; };
};
}

Просмотреть файл

@ -128,8 +128,8 @@
<DependentUpon>ReactApplicationDelegate.idl</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="ReactContext.h">
<DependentUpon>ReactContext.idl</DependentUpon>
<ClInclude Include="IReactContext.h">
<DependentUpon>IReactContext.idl</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="ReactInstanceCreator.h" />
@ -184,8 +184,8 @@
<DependentUpon>ReactApplicationDelegate.idl</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="ReactContext.cpp">
<DependentUpon>ReactContext.idl</DependentUpon>
<ClCompile Include="IReactContext.cpp">
<DependentUpon>IReactContext.idl</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="ReactInstanceCreator.cpp" />
@ -229,7 +229,7 @@
<Midl Include="ReactApplicationDelegate.idl">
<SubType>Designer</SubType>
</Midl>
<Midl Include="ReactContext.idl">
<Midl Include="IReactContext.idl">
<SubType>Designer</SubType>
</Midl>
<Midl Include="ReactInstance.idl">

Просмотреть файл

@ -1,42 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "ReactContext.h"
#if __has_include("Bridge.ReactContext.g.cpp")
#include "Bridge.ReactContext.g.cpp"
#endif
using namespace winrt;
using namespace Microsoft::ReactNative::Bridge;
using namespace Windows::Foundation::Collections;
namespace winrt::Microsoft::ReactNative::Bridge::implementation {
IReactInstance ReactContext::ReactInstance() {
if (m_reactInstance == nullptr) {
throw hresult_invalid_operation(L"ReactInstance has not yet been set.");
}
return m_reactInstance;
}
void ReactContext::InitializeWithInstance(Bridge::ReactInstance const &instance) {
if (instance == nullptr) {
throw hresult_null_argument(L"instance");
}
if (m_reactInstance != nullptr) {
throw hresult_invalid_argument(L"ReactInstance has already been set.");
}
m_reactInstance = instance;
}
void ReactContext::CallJSFunction(
hstring const &moduleName,
hstring const &method,
IVectorView<IInspectable> const &params) {
if (m_reactInstance == nullptr) {
ReactInstance().InvokeFunction(moduleName, method, params);
}
}
} // namespace winrt::Microsoft::ReactNative::Bridge::implementation

Просмотреть файл

@ -1,29 +0,0 @@
#pragma once
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "Bridge.ReactContext.g.h"
#include "ReactInstance.h"
using namespace winrt;
using namespace Windows::Foundation::Collections;
namespace winrt::Microsoft::ReactNative::Bridge::implementation {
struct ReactContext : ReactContextT<ReactContext> {
ReactContext() = default;
IReactInstance ReactInstance();
void InitializeWithInstance(Bridge::ReactInstance const &instance);
void CallJSFunction(hstring const &moduleName, hstring const &method, IVectorView<IInspectable> const &params);
private:
Bridge::ReactInstance m_reactInstance{nullptr};
};
} // namespace winrt::Microsoft::ReactNative::Bridge::implementation
namespace winrt::Microsoft::ReactNative::Bridge::factory_implementation {
struct ReactContext : ReactContextT<ReactContext, implementation::ReactContext> {};
} // namespace winrt::Microsoft::ReactNative::Bridge::factory_implementation

Просмотреть файл

@ -1,22 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import "ReactInstance.idl";
namespace Microsoft.ReactNative.Bridge
{
[webhosthidden]
runtimeclass ReactContext
{
ReactContext();
IReactInstance ReactInstance { get; };
// TODO: Look at supporting this functionality as used by modules
/*
void AddLifecycleEventListener(ILifecycleEventListener listener);
void RemoveLifecycleEventListener(ILifecycleEventListener listener);
void AddBackgroundEventListener(IBackgroundEventListener listener);
void RemoveBackgroundEventListener(IBackgroundEventListener listener);
*/
}
}

Просмотреть файл

@ -121,7 +121,7 @@ std::shared_ptr<react::uwp::IReactInstanceCreator> ReactInstanceManager::Instanc
return m_reactInstanceCreator;
}
auto ReactInstanceManager::GetOrCreateReactContextAsync() -> IAsyncOperation<ReactContext> {
auto ReactInstanceManager::GetOrCreateReactContextAsync() -> IAsyncOperation<IReactContext> {
if (m_currentReactContext != nullptr)
co_return m_currentReactContext;
@ -132,9 +132,7 @@ auto ReactInstanceManager::GetOrCreateReactContextAsync() -> IAsyncOperation<Rea
// TODO: Should we make this method async? On first run when getInstance
// is called it starts things up. Does this need to block?
auto ReactInstanceManager::CreateReactContextCoreAsync() -> IAsyncOperation<ReactContext> {
auto reactContext = ReactContext();
auto ReactInstanceManager::CreateReactContextCoreAsync() -> IAsyncOperation<IReactContext> {
/* TODO hook up an exception handler if UseDeveloperSupport is set
if (m_useDeveloperSupport) {
if (m_nativeModuleCallExceptionHandler) {
@ -175,11 +173,10 @@ auto ReactInstanceManager::CreateReactContextCoreAsync() -> IAsyncOperation<Reac
// TODO: Could access to the module registry be easier if the ReactInstance
// implementation were lifted up into this project.
auto instancePtr = InstanceCreator()->getInstance();
auto reactInstance = winrt::make<Bridge::implementation::ReactInstance>(instancePtr);
auto reactInstance = InstanceCreator()->getInstance();
Bridge::implementation::ReactContext *contextImpl{get_self<Bridge::implementation::ReactContext>(reactContext)};
contextImpl->InitializeWithInstance(reactInstance);
auto reactContext =
winrt::make<winrt::Microsoft::ReactNative::Bridge::ReactContext>(reactInstance).as<IReactContext>();
// TODO: Investigate whether we need the equivalent of the
// LimitedConcurrencyActionQueue from the C# implementation that is used to

Просмотреть файл

@ -4,9 +4,9 @@
#include "ReactInstanceManager.g.h"
#include "IReactContext.h"
#include "LifecycleState.h"
#include "NativeModulesProvider.h"
#include "ReactContext.h"
#include "ReactInstanceSettings.h"
#include "ViewManagersProvider.h"
@ -30,8 +30,8 @@ struct ReactInstanceManager : ReactInstanceManagerT<ReactInstanceManager> {
bool useDeveloperSupport,
LifecycleState initialLifecycleState);
IAsyncOperation<ReactContext> GetOrCreateReactContextAsync();
ReactContext CurrentReactContext() {
IAsyncOperation<IReactContext> GetOrCreateReactContextAsync();
IReactContext CurrentReactContext() {
return m_currentReactContext;
}
@ -51,7 +51,7 @@ struct ReactInstanceManager : ReactInstanceManagerT<ReactInstanceManager> {
void OnBackPressed();
private:
ReactContext m_currentReactContext{nullptr};
IReactContext m_currentReactContext{nullptr};
Microsoft::ReactNative::ReactInstanceSettings m_instanceSettings{nullptr};
std::string m_jsBundleFile{};
std::string m_jsMainModuleName{};
@ -66,7 +66,7 @@ struct ReactInstanceManager : ReactInstanceManagerT<ReactInstanceManager> {
// instances on live reload.
std::shared_ptr<react::uwp::IReactInstanceCreator> m_reactInstanceCreator{nullptr};
IAsyncOperation<ReactContext> CreateReactContextCoreAsync();
IAsyncOperation<IReactContext> CreateReactContextCoreAsync();
};
} // namespace winrt::Microsoft::ReactNative::implementation

Просмотреть файл

@ -2,7 +2,7 @@
// Licensed under the MIT License.
import "ReactNativeHost.idl";
import "ReactContext.idl";
import "IReactContext.idl";
namespace Microsoft.ReactNative
{
@ -10,7 +10,7 @@ namespace Microsoft.ReactNative
runtimeclass ReactInstanceManager
{
ReactInstanceManager();
Microsoft.ReactNative.Bridge.ReactContext CurrentReactContext();
Microsoft.ReactNative.Bridge.IReactContext CurrentReactContext();
void OnSuspend();
void OnEnteredBackground();
void OnLeavingBackground();

Просмотреть файл

@ -12,6 +12,14 @@ folly::dynamic ConvertToDynamic(IInspectable const &object) {
if (object == nullptr)
return nullptr;
if (auto const &map = object.try_as<IMapView<hstring, IInspectable>>()) {
folly::dynamic obj = folly::dynamic::object;
for (auto const &kvp : map) {
obj[to_string(kvp.Key())] = ConvertToDynamic(kvp.Value());
}
return obj;
}
auto propValue = object.try_as<IPropertyValue>();
if (!propValue) {
auto stringable = object.try_as<IStringable>();

Просмотреть файл

@ -4,6 +4,8 @@
#include "pch.h"
#include "ViewManagersProvider.h"
#include "IReactContext.h"
#include "ABIViewManager.h"
namespace winrt::Microsoft::ReactNative::Bridge {
@ -17,7 +19,8 @@ std::vector<react::uwp::NativeViewManager> ViewManagersProvider::GetViewManagers
for (auto &entry : m_viewManagerProviders) {
auto viewManagerProvider = entry.second;
auto viewManager = std::make_unique<ABIViewManager>(instance, viewManagerProvider());
auto reactContext = winrt::make<ReactContext>(instance).as<IReactContext>();
auto viewManager = std::make_unique<ABIViewManager>(instance, viewManagerProvider(reactContext));
viewManagers.emplace_back(std::move(viewManager));
}