From 2a2a28811fddbfc66edc5e097165e2f992e6802b Mon Sep 17 00:00:00 2001 From: Olly Levett Date: Tue, 7 Mar 2017 21:18:05 +0000 Subject: [PATCH 1/3] fix: prevent view locator from erroring if name convention fails Fixes #1298 --- src/ReactiveUI.Tests/ViewLocatorTests.cs | 23 ++++++++++++++++++++++- src/ReactiveUI/ViewLocator.cs | 5 ++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/ReactiveUI.Tests/ViewLocatorTests.cs b/src/ReactiveUI.Tests/ViewLocatorTests.cs index f390b4dca1..96f0cb2a90 100644 --- a/src/ReactiveUI.Tests/ViewLocatorTests.cs +++ b/src/ReactiveUI.Tests/ViewLocatorTests.cs @@ -1,5 +1,4 @@ using System; -using ReactiveUI; using Splat; using Xunit; @@ -72,6 +71,10 @@ object IViewFor.ViewModel public IFooViewModel ViewModel { get; set; } } + public interface StrangeInterfaceNotFollowingConvention { } + + public class StrangeClassNotFollowingConvention : StrangeInterfaceNotFollowingConvention { } + public class DefaultViewLocatorTests { [Fact] @@ -332,5 +335,23 @@ public void AnErrorIsRaisedIfTheCreationOfTheViewFails() Assert.Equal("This is a test failure.", ex.Message); } } + + [Fact] + public void WithOddInterfaceNameDoesntThrowException() + { + var resolver = new ModernDependencyResolver(); + + resolver.InitializeSplat(); + resolver.InitializeReactiveUI(); + + using (resolver.WithResolver()) { + var fixture = new DefaultViewLocator(); + + var vm = new StrangeClassNotFollowingConvention(); + + fixture.ResolveView((StrangeInterfaceNotFollowingConvention)vm); + } + + } } } \ No newline at end of file diff --git a/src/ReactiveUI/ViewLocator.cs b/src/ReactiveUI/ViewLocator.cs index c7eb8a5fe0..5fb2f376d0 100755 --- a/src/ReactiveUI/ViewLocator.cs +++ b/src/ReactiveUI/ViewLocator.cs @@ -106,7 +106,10 @@ public IViewFor ResolveView(T viewModel, string contract = null) } var toggledType = ToggleViewModelType(viewModel); - view = this.AttemptViewResolutionFor(toggledType, contract); + + if (toggledType != null) { + view = this.AttemptViewResolutionFor(toggledType, contract); + } if (view != null) { return view; From 0c2ef950c15a8c2d5c7a9f07c1338dd64b1bc7a3 Mon Sep 17 00:00:00 2001 From: Olly Levett Date: Tue, 7 Mar 2017 21:24:52 +0000 Subject: [PATCH 2/3] fix: correctly resolve IRoutableViewModel types Fixes #1299 --- src/ReactiveUI.Tests/ViewLocatorTests.cs | 36 ++++++++++++++++++++++++ src/ReactiveUI/ViewLocator.cs | 12 ++++---- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/ReactiveUI.Tests/ViewLocatorTests.cs b/src/ReactiveUI.Tests/ViewLocatorTests.cs index 96f0cb2a90..b03bb55047 100644 --- a/src/ReactiveUI.Tests/ViewLocatorTests.cs +++ b/src/ReactiveUI.Tests/ViewLocatorTests.cs @@ -75,6 +75,25 @@ public interface StrangeInterfaceNotFollowingConvention { } public class StrangeClassNotFollowingConvention : StrangeInterfaceNotFollowingConvention { } + public interface IRoutableFooViewModel : IRoutableViewModel { } + + public class RoutableFooViewModel : ReactiveObject, IRoutableFooViewModel + { + public IScreen HostScreen { get; set; } + public string UrlPathSegment { get; set; } + } + + public class RoutableFooView : IViewFor + { + object IViewFor.ViewModel + { + get { return ViewModel; } + set { ViewModel = (IRoutableFooViewModel)value; } + } + public IRoutableFooViewModel ViewModel { get; set; } + } + + public class DefaultViewLocatorTests { [Fact] @@ -351,7 +370,24 @@ public void WithOddInterfaceNameDoesntThrowException() fixture.ResolveView((StrangeInterfaceNotFollowingConvention)vm); } + } + + [Fact] + public void CanResolveViewFromViewModelWithIRoutableViewModelType() + { + var resolver = new ModernDependencyResolver(); + + resolver.InitializeSplat(); + resolver.InitializeReactiveUI(); + resolver.Register(() => new RoutableFooView(), typeof(IViewFor)); + + using (resolver.WithResolver()) { + var fixture = new DefaultViewLocator(); + var vm = new RoutableFooViewModel(); + var result = fixture.ResolveView(vm); + Assert.IsType(result); + } } } } \ No newline at end of file diff --git a/src/ReactiveUI/ViewLocator.cs b/src/ReactiveUI/ViewLocator.cs index 5fb2f376d0..5bccaf20c9 100755 --- a/src/ReactiveUI/ViewLocator.cs +++ b/src/ReactiveUI/ViewLocator.cs @@ -105,12 +105,14 @@ public IViewFor ResolveView(T viewModel, string contract = null) return view; } - var toggledType = ToggleViewModelType(viewModel); + view = this.AttemptViewResolutionFor(ToggleViewModelType(viewModel.GetType()), contract); - if (toggledType != null) { - view = this.AttemptViewResolutionFor(toggledType, contract); + if (view != null) { + return view; } + view = this.AttemptViewResolutionFor(ToggleViewModelType(typeof(T)), contract); + if (view != null) { return view; } @@ -121,6 +123,7 @@ public IViewFor ResolveView(T viewModel, string contract = null) private IViewFor AttemptViewResolutionFor(Type viewModelType, string contract) { + if (viewModelType == null) return null; var viewModelTypeName = viewModelType.AssemblyQualifiedName; var proposedViewTypeName = this.ViewModelToViewFunc(viewModelTypeName); var view = this.AttemptViewResolution(proposedViewTypeName, contract); @@ -170,9 +173,8 @@ private IViewFor AttemptViewResolution(string viewTypeName, string contract) } } - private static Type ToggleViewModelType(T viewModel) + private static Type ToggleViewModelType(Type viewModelType) { - var viewModelType = typeof(T); var viewModelTypeName = viewModelType.AssemblyQualifiedName; if (viewModelType.GetTypeInfo().IsInterface) { From a97270bd39f853cadb6483f95f8c538ecfa66a27 Mon Sep 17 00:00:00 2001 From: Olly Levett Date: Mon, 22 May 2017 09:38:46 +0100 Subject: [PATCH 3/3] fix: update xmldoc to match functionality --- src/ReactiveUI/ViewLocator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ReactiveUI/ViewLocator.cs b/src/ReactiveUI/ViewLocator.cs index 5bccaf20c9..d5ba931cc5 100755 --- a/src/ReactiveUI/ViewLocator.cs +++ b/src/ReactiveUI/ViewLocator.cs @@ -78,7 +78,7 @@ public DefaultViewLocator(Func viewModelToViewFunc = null) /// /// /// - /// Repeat steps 1 and 2 with the type resolved from the modified name. + /// Repeat steps 1-4 with the type resolved from the modified name. /// /// ///