Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move ViewRegistry to Prism.Core #2886

Merged
merged 1 commit into from
Jun 13, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Maui/Prism.Maui/Ioc/DialogRegistrationExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Prism.Common;
using Prism.Mvvm;
using Prism.Services;

namespace Prism.Ioc;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Prism.Common;
using Prism.Mvvm;

namespace Prism.Ioc;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Prism.Common;
using Prism.Mvvm;

namespace Prism.Ioc;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Microsoft.Maui.Controls.Compatibility;
using Prism.Common;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Regions.Adapters;
using Prism.Regions.Behaviors;
Expand Down
19 changes: 0 additions & 19 deletions src/Maui/Prism.Maui/Mvvm/IViewRegistry.cs

This file was deleted.

18 changes: 0 additions & 18 deletions src/Maui/Prism.Maui/Mvvm/ViewModelCreationException.cs

This file was deleted.

145 changes: 13 additions & 132 deletions src/Maui/Prism.Maui/Mvvm/ViewRegistryBase.cs
Original file line number Diff line number Diff line change
@@ -1,154 +1,35 @@
using System.Text.RegularExpressions;
using System.Xml.Linq;
using Prism.Common;
using Prism.Ioc;
using Prism.Ioc;
using Prism.Navigation.Xaml;

namespace Prism.Mvvm;

public abstract class ViewRegistryBase : IViewRegistry
public abstract class ViewRegistryBase : ViewRegistryBase<BindableObject>
{
private readonly IEnumerable<ViewRegistration> _registrations;
private readonly ViewType _registryType;

protected ViewRegistryBase(ViewType registryType, IEnumerable<ViewRegistration> registrations)
: base(registryType, registrations)
{
_registrations = registrations;
_registryType = registryType;
}

public IEnumerable<ViewRegistration> Registrations =>
_registrations.Where(x => x.Type == _registryType);

public Type GetViewType(string name) =>
GetRegistration(name)?.View;

public object CreateView(IContainerProvider container, string name)
protected override void Autowire(BindableObject view)
{
try
{
var registration = GetRegistration(name);
if (registration is null)
throw new KeyNotFoundException($"No view with the name '{name}' has been registered");

var view = container.Resolve(registration.View) as BindableObject;
view.SetValue(ViewModelLocator.NavigationNameProperty, registration.Name);

view.SetContainerProvider(container);
ConfigureView(view, container);

if (registration.ViewModel is not null)
view.SetValue(ViewModelLocator.ViewModelProperty, registration.ViewModel);

Autowire(view);
if (view.BindingContext is not null)
return;

return view;
}
catch (KeyNotFoundException)
{
throw;
}
catch (ViewModelCreationException)
{
throw;
}
catch (Exception ex)
{
throw new ViewCreationException(name, _registryType, ex);
}
ViewModelLocator.Autowire(view);
}

private IEnumerable<Type> GetCandidates(Type viewModelType)
protected override void SetContainerProvider(BindableObject view, IContainerProvider container)
{
var names = new List<string>
{
Regex.Replace(viewModelType.Name, @"ViewModel$", string.Empty),
Regex.Replace(viewModelType.Name, @"Model$", string.Empty),
};

if (_registryType == ViewType.Page)
names.Add(Regex.Replace(viewModelType.Name, @"ViewModel$", "Page"));
else if (_registryType == ViewType.Region)
names.Add(Regex.Replace(viewModelType.Name, @"ViewModel$", "Region"));
else if (_registryType == ViewType.Dialog)
names.Add(Regex.Replace(viewModelType.Name, @"ViewModel$", "Dialog"));

names = names.Where(x => !x.EndsWith("PagePage")).ToList();

var namespaces = _registryType switch
{
ViewType.Page => new[]
{
viewModelType.Namespace.Replace("ViewModels", "Views"),
viewModelType.Namespace.Replace("ViewModels", "Pages")
},
ViewType.Region => new[]
{
viewModelType.Namespace.Replace("ViewModels", "Views"),
viewModelType.Namespace.Replace("ViewModels", "Regions")
},
ViewType.Dialog => new[]
{
viewModelType.Namespace.Replace("ViewModels", "Views"),
viewModelType.Namespace.Replace("ViewModels", "Dialogs")
},
_ => new[]
{
viewModelType.Namespace.Replace("ViewModels", "Views"),
}
};

var candidates = namespaces.Select(@namespace => names.Select(name => $"{@namespace}.{name}"))
.SelectMany(x => x)
.Select(x => viewModelType.AssemblyQualifiedName.Replace(viewModelType.FullName, x));
return candidates
.Select(x => Type.GetType(x, false))
.Where(x => x is not null);
view.SetContainerProvider(container);
}

public string GetViewModelNavigationKey(Type viewModelType)
protected override void SetNavigationNameProperty(BindableObject view, string name)
{
var registration = Registrations.LastOrDefault(x => x.ViewModel == viewModelType);
if (registration is not null)
return registration.Name;

var candidates = GetCandidates(viewModelType);
registration = Registrations.LastOrDefault(x => candidates.Any(c => c == x.View));
if (registration is not null)
{
return registration.Name;
}

throw new KeyNotFoundException($"No View with the ViewModel '{viewModelType.Name}' has been registered");
view.SetValue(ViewModelLocator.NavigationNameProperty, name);
}

public IEnumerable<ViewRegistration> ViewsOfType(Type baseType) =>
Registrations.Where(x => x.View == baseType || x.View.IsAssignableTo(baseType));

public bool IsRegistered(string name) =>
GetRegistration(name) is not null;

protected ViewRegistration GetRegistration(string name) =>
Registrations.LastOrDefault(x => x.Name == name);

protected abstract void ConfigureView(BindableObject bindable, IContainerProvider container);

protected void Autowire(BindableObject view)
protected override void SetViewModelProperty(BindableObject view, Type viewModelType)
{
if (view.BindingContext is not null)
return;

ViewModelLocator.Autowire(view);
view.SetValue(ViewModelLocator.ViewModelProperty, viewModelType);
}

//public static Type GetPageType(string name)
//{
// var registrations = _registrations.Where(x => x.Name == name);
// if (!registrations.Any())
// throw new KeyNotFoundException(name);
// if (registrations.Count() > 1)
// throw new InvalidOperationException(string.Format(Resources.MultipleViewsRegisteredForNavigationKey, name, string.Join(", ", registrations.Select(x => x.View.FullName))));

// return registrations.First().View;
//}
}
8 changes: 8 additions & 0 deletions src/Maui/Prism.Maui/PrismAppBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ internal PrismAppBuilder(IContainerExtension containerExtension, MauiAppBuilder
_registrations = new List<Action<IContainerRegistry>>();
_initializations = new List<Action<IContainerProvider>>();

ViewModelCreationException.SetViewNameDelegate(view =>
{
if (view is BindableObject bindable)
return Mvvm.ViewModelLocator.GetNavigationName(bindable);

return $"View is not a BindableObject: '{view.GetType().FullName}";
});

MauiBuilder = builder;
MauiBuilder.ConfigureContainer(new PrismServiceProviderFactory(RegistrationCallback));
MauiBuilder.ConfigureLifecycleEvents(lifecycle =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Prism.Common;
using Prism.Ioc;
using Prism.Ioc.Internals;
using Prism.Mvvm;
using Prism.Properties;

namespace Prism.Regions.Navigation;
Expand Down
3 changes: 1 addition & 2 deletions src/Maui/Prism.Maui/Regions/RegionNavigationRegistry.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Prism.Common;
using Prism.Ioc;
using Prism.Ioc;
using Prism.Mvvm;

namespace Prism.Regions;
Expand Down
1 change: 1 addition & 0 deletions src/Maui/Prism.Maui/Regions/RegionViewRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Prism.Common;
using Prism.Events;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Properties;

namespace Prism.Regions;
Expand Down
1 change: 0 additions & 1 deletion src/Maui/Prism.Maui/Services/Dialogs/DialogViewRegistry.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Common;

namespace Prism.Services;

Expand Down
File renamed without changes.
52 changes: 52 additions & 0 deletions src/Prism.Core/Mvvm/IViewRegistry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using Prism.Ioc;

namespace Prism.Mvvm;

/// <summary>
/// Provides an abstraction layer for ViewRegistration that can be mocked
/// </summary>
public interface IViewRegistry
{
/// <summary>
/// The existing ViewRegistrations
/// </summary>
IEnumerable<ViewRegistration> Registrations { get; }

/// <summary>
/// Creates a view given a specified instance of the Container and a navigation name
/// </summary>
/// <param name="container"></param>
/// <param name="name"></param>
/// <returns></returns>
object CreateView(IContainerProvider container, string name);

/// <summary>
/// Gets the ViewType for a specified navigation name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
Type GetViewType(string name);

/// <summary>
/// Gets the navigation name for a specified ViewModelType
/// </summary>
/// <param name="viewModelType"></param>
/// <returns></returns>
string GetViewModelNavigationKey(Type viewModelType);

/// <summary>
/// Gets the Registrations where the View is of a given base type
/// </summary>
/// <param name="baseType"></param>
/// <returns></returns>
IEnumerable<ViewRegistration> ViewsOfType(Type baseType);

/// <summary>
/// Confirms whether the given navigation name has been registered
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
bool IsRegistered(string name);
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
using Prism.Common;
using System;

namespace Prism.Mvvm;

public class ViewCreationException : Exception

Check warning on line 5 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-maui / Build Prism.Maui

Missing XML comment for publicly visible type or member 'ViewCreationException'

Check warning on line 5 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-uno / Build Prism.Uno

Missing XML comment for publicly visible type or member 'ViewCreationException'

Check warning on line 5 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-core / Build Prism.Core

Missing XML comment for publicly visible type or member 'ViewCreationException'

Check warning on line 5 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-wpf / Build Prism.Wpf

Missing XML comment for publicly visible type or member 'ViewCreationException'
{
public ViewCreationException(string viewName, ViewType viewType)

Check warning on line 7 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-maui / Build Prism.Maui

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewCreationException(string, ViewType)'

Check warning on line 7 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-uno / Build Prism.Uno

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewCreationException(string, ViewType)'

Check warning on line 7 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-core / Build Prism.Core

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewCreationException(string, ViewType)'

Check warning on line 7 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-wpf / Build Prism.Wpf

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewCreationException(string, ViewType)'
: this(viewName, viewType, null)
{
}

public ViewCreationException(string viewName, ViewType viewType, Exception innerException)

Check warning on line 12 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-maui / Build Prism.Maui

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewCreationException(string, ViewType, Exception)'

Check warning on line 12 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-uno / Build Prism.Uno

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewCreationException(string, ViewType, Exception)'

Check warning on line 12 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-core / Build Prism.Core

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewCreationException(string, ViewType, Exception)'

Check warning on line 12 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-wpf / Build Prism.Wpf

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewCreationException(string, ViewType, Exception)'
: base($"Unable to create {viewType} '{viewName}'.", innerException)
{
ViewName = viewName;
ViewType = viewType;
}

public ViewType ViewType { get; }

Check warning on line 19 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-maui / Build Prism.Maui

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewType'

Check warning on line 19 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-uno / Build Prism.Uno

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewType'

Check warning on line 19 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-core / Build Prism.Core

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewType'

Check warning on line 19 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-wpf / Build Prism.Wpf

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewType'

public string ViewName { get; }

Check warning on line 21 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-maui / Build Prism.Maui

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewName'

Check warning on line 21 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-uno / Build Prism.Uno

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewName'

Check warning on line 21 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-core / Build Prism.Core

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewName'

Check warning on line 21 in src/Prism.Core/Mvvm/ViewCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-wpf / Build Prism.Wpf

Missing XML comment for publicly visible type or member 'ViewCreationException.ViewName'
}
24 changes: 24 additions & 0 deletions src/Prism.Core/Mvvm/ViewModelCreationException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.ComponentModel;

namespace Prism.Mvvm;

public class ViewModelCreationException : Exception

Check warning on line 6 in src/Prism.Core/Mvvm/ViewModelCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-maui / Build Prism.Maui

Missing XML comment for publicly visible type or member 'ViewModelCreationException'

Check warning on line 6 in src/Prism.Core/Mvvm/ViewModelCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-uno / Build Prism.Uno

Missing XML comment for publicly visible type or member 'ViewModelCreationException'

Check warning on line 6 in src/Prism.Core/Mvvm/ViewModelCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-core / Build Prism.Core

Missing XML comment for publicly visible type or member 'ViewModelCreationException'

Check warning on line 6 in src/Prism.Core/Mvvm/ViewModelCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-wpf / Build Prism.Wpf

Missing XML comment for publicly visible type or member 'ViewModelCreationException'
{
private static Func<object, string> _viewNameDelegate = null;
private static string GetViewName(object view) => _viewNameDelegate is null ? "Platform not initialized" : _viewNameDelegate(view);

[EditorBrowsable(EditorBrowsableState.Never)]
public static void SetViewNameDelegate(Func<object, string> viewNameDelegate) => _viewNameDelegate = viewNameDelegate;

Check warning on line 12 in src/Prism.Core/Mvvm/ViewModelCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-maui / Build Prism.Maui

Missing XML comment for publicly visible type or member 'ViewModelCreationException.SetViewNameDelegate(Func<object, string>)'

Check warning on line 12 in src/Prism.Core/Mvvm/ViewModelCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-uno / Build Prism.Uno

Missing XML comment for publicly visible type or member 'ViewModelCreationException.SetViewNameDelegate(Func<object, string>)'

Check warning on line 12 in src/Prism.Core/Mvvm/ViewModelCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-core / Build Prism.Core

Missing XML comment for publicly visible type or member 'ViewModelCreationException.SetViewNameDelegate(Func<object, string>)'

Check warning on line 12 in src/Prism.Core/Mvvm/ViewModelCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-wpf / Build Prism.Wpf

Missing XML comment for publicly visible type or member 'ViewModelCreationException.SetViewNameDelegate(Func<object, string>)'

public ViewModelCreationException(object view, Exception innerException)

Check warning on line 14 in src/Prism.Core/Mvvm/ViewModelCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-maui / Build Prism.Maui

Missing XML comment for publicly visible type or member 'ViewModelCreationException.ViewModelCreationException(object, Exception)'

Check warning on line 14 in src/Prism.Core/Mvvm/ViewModelCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-uno / Build Prism.Uno

Missing XML comment for publicly visible type or member 'ViewModelCreationException.ViewModelCreationException(object, Exception)'

Check warning on line 14 in src/Prism.Core/Mvvm/ViewModelCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-core / Build Prism.Core

Missing XML comment for publicly visible type or member 'ViewModelCreationException.ViewModelCreationException(object, Exception)'

Check warning on line 14 in src/Prism.Core/Mvvm/ViewModelCreationException.cs

View workflow job for this annotation

GitHub Actions / build-prism-wpf / Build Prism.Wpf

Missing XML comment for publicly visible type or member 'ViewModelCreationException.ViewModelCreationException(object, Exception)'
: base($"Unable to Create ViewModel for '{view.GetType().FullName}'.", innerException)
{
View = view;
ViewName = GetViewName(view);
}

public string ViewName { get; }

public object View { get; }
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Prism.Common;
using System;

namespace Prism.Mvvm;

public record ViewRegistration
{
Expand Down