Skip to content

Commit

Permalink
Merge pull request #1780 from PrismLibrary/automatic-registration
Browse files Browse the repository at this point in the history
Automatic View Registration
  • Loading branch information
dansiegel committed Apr 25, 2019
2 parents ae667e7 + 5c11a75 commit d5569a5
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 15 deletions.
30 changes: 15 additions & 15 deletions Source/Xamarin/Prism.Forms/AppModel/RuntimePlatform.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
namespace Prism.AppModel
{
/// <summary>
/// Represents the Platform (OS) that the application is running on.
/// </summary>
/// <remarks>This enum acts as a wrapper around the Device.RuntimePlatform string-based options</remarks>
public enum RuntimePlatform
{
Android,
iOS,
macOS,
Tizen,
UWP,
WinPhone,
WinRT,
Unknown
}
/// <summary>
/// Represents the Platform (OS) that the application is running on.
/// </summary>
/// <remarks>This enum acts as a wrapper around the Device.RuntimePlatform string-based options</remarks>
public enum RuntimePlatform
{
Android,
iOS,
macOS,
Tizen,
UWP,
WinPhone,
WinRT,
Unknown
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;

namespace Prism.Ioc
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class AutoRegisterForNavigationAttribute : Attribute
{
public bool Automatic { get; set; }
}
}
14 changes: 14 additions & 0 deletions Source/Xamarin/Prism.Forms/Ioc/RegisterForNavigationAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Prism.AppModel;
using System;

namespace Prism.Ioc
{
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = true)]
public class RegisterForNavigationAttribute : Attribute
{
public Type ViewType { get; set; }
public Type ViewModelType { get; set; }
public string Name { get; set; }
public RuntimePlatform? RuntimePlatform { get; set; }
}
}
88 changes: 88 additions & 0 deletions Source/Xamarin/Prism.Forms/Ioc/TypeAutoLoadExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Xamarin.Forms;

namespace Prism.Ioc
{
internal static class IContainerRegistryAutoLoadExtensions
{
public static void AutoRegisterViews(this Type type, IContainerRegistry containerRegistry)
{
if (!type.GetCustomAttributes().Any(a => a is AutoRegisterForNavigationAttribute)) return;

var regAttr = type.GetCustomAttribute<AutoRegisterForNavigationAttribute>();
var assembly = type.Assembly;

if (regAttr.Automatic)
{
var viewTypes = assembly.ExportedTypes.Where(t => t.IsSubclassOf(typeof(Page)));
RegisterViewsAutomatically(containerRegistry, viewTypes);
}
else
{
RegisterViewsByAttribute(containerRegistry, assembly);
}
}

private static void RegisterViewsAutomatically(IContainerRegistry containerRegistry, IEnumerable<Type> viewTypes)
{
foreach (var viewType in viewTypes)
{
containerRegistry.RegisterForNavigation(viewType, viewType.Name);
}

if (!containerRegistry.IsRegistered<object>(nameof(NavigationPage)))
{
containerRegistry.RegisterForNavigation<NavigationPage>();
}

if (!containerRegistry.IsRegistered<object>(nameof(TabbedPage)))
{
containerRegistry.RegisterForNavigation<TabbedPage>();
}
}

private static void RegisterViewsByAttribute(IContainerRegistry containerRegistry, Assembly assembly)
{
var attrs = assembly.GetCustomAttributes<RegisterForNavigationAttribute>();
foreach (var attr in attrs)
{
RegisterViewByAttribute(containerRegistry, attr);
}

var viewTypes = assembly.ExportedTypes.Where(t => t.IsSubclassOf(typeof(Page))
&& t.GetCustomAttributes<RegisterForNavigationAttribute>().Any());
foreach (var viewType in viewTypes)
{
var attr = viewType.GetCustomAttributes<RegisterForNavigationAttribute>()
.FirstOrDefault(a => a.RuntimePlatform.ToString() == Device.RuntimePlatform || a.RuntimePlatform is null);
attr.ViewType = viewType;
RegisterViewByAttribute(containerRegistry, attr);
}
}

private static void RegisterViewByAttribute(IContainerRegistry containerRegistry, RegisterForNavigationAttribute attr)
{
if (attr.ViewType is null)
throw new Exception($"Cannot auto register View. No ViewType was specified. Name: '{attr.Name}'. ViewModelType: '{attr.ViewModelType?.Name}'");

if (attr.RuntimePlatform != null && attr.RuntimePlatform.ToString() != Device.RuntimePlatform) return;

var name = attr.Name;
if (string.IsNullOrEmpty(name))
{
name = attr.ViewType.Name;
}

containerRegistry.RegisterForNavigation(attr.ViewType, name);

if (attr.ViewModelType != null)
{
ViewModelLocationProvider.Register(attr.ViewType.Name, attr.ViewModelType);
}
}
}
}
1 change: 1 addition & 0 deletions Source/Xamarin/Prism.Forms/Modularity/ModuleInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public void Initialize(IModuleInfo moduleInfo)
if (module != null)
{
module.RegisterTypes(_container);
module.GetType().AutoRegisterViews(_container);
module.OnInitialized(_container);
}
}
Expand Down
1 change: 1 addition & 0 deletions Source/Xamarin/Prism.Forms/PrismApplicationBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ public virtual void Initialize()
RegisterRequiredTypes(_containerExtension);
PlatformInitializer?.RegisterTypes(_containerExtension);
RegisterTypes(_containerExtension);
GetType().AutoRegisterViews(_containerExtension);
_containerExtension.FinalizeExtension();

if(_setFormsDependencyResolver)
Expand Down

0 comments on commit d5569a5

Please sign in to comment.