Add support for namespace transformations to ViewManager

This commit is contained in:
Antony Male 2015-09-25 10:57:46 +01:00
parent 3dd1ec2bfe
commit 8a6f010fbb
2 changed files with 74 additions and 7 deletions

View File

@ -49,7 +49,7 @@ namespace Stylet
/// </summary>
public class ViewManagerConfig
{
private List<Assembly> _viewAssemblies;
private List<Assembly> _viewAssemblies = new List<Assembly>();
/// <summary>
/// Gets and sets the assemblies which are used for IoC container auto-binding and searching for Views.
@ -70,12 +70,21 @@ namespace Stylet
/// </summary>
public Func<Type, object> ViewFactory { get; set; }
private Dictionary<string, string> _namespaceTransformations = new Dictionary<string, string>();
/// <summary>
/// Instantiates a new instance of the <see cref="ViewManagerConfig"/> class
/// Gets and sets a set of transformations to be applied to the ViewModel's namespace: string to find -> string to replace it with
/// </summary>
public ViewManagerConfig()
public Dictionary<string, string> NamespaceTransformations
{
this.ViewAssemblies = new List<Assembly>();
get { return this._namespaceTransformations; }
set
{
if (value == null)
throw new ArgumentNullException();
this._namespaceTransformations = value;
}
}
}
@ -96,6 +105,11 @@ namespace Stylet
/// </summary>
protected Func<Type, object> ViewFactory { get; set; }
/// <summary>
/// Gets and sets a set of transformations to be applied to the ViewModel's namespace: string to find -> string to replace it with
/// </summary>
protected Dictionary<string, string> NamespaceTransformations { get; set; }
/// <summary>
/// Initialises a new instance of the <see cref="ViewManager"/> class, with the given viewFactory
/// </summary>
@ -105,8 +119,10 @@ namespace Stylet
// Config.ViewAssemblies cannot be null - ViewManagerConfig ensures this
if (config.ViewFactory == null)
throw new ArgumentNullException("config.ViewFactory");
this.ViewAssemblies = config.ViewAssemblies;
this.ViewFactory = config.ViewFactory;
this.NamespaceTransformations = config.NamespaceTransformations;
}
/// <summary>
@ -193,7 +209,19 @@ namespace Stylet
/// <returns>View type name</returns>
protected virtual string ViewTypeNameForModelTypeName(string modelTypeName)
{
return Regex.Replace(modelTypeName, @"(?<=.)ViewModel(?=s?\.)|ViewModel$", "View");
string transformed = modelTypeName;
foreach (var transformation in this.NamespaceTransformations)
{
if (transformed.StartsWith(transformation.Key + "."))
{
transformed = transformation.Value + transformed.Substring(transformation.Key.Length);
break;
}
}
transformed = Regex.Replace(transformed, @"(?<=.)ViewModel(?=s?\.)|ViewModel$", "View");
return transformed;
}
/// <summary>

View File

@ -132,6 +132,27 @@ namespace StyletUnitTests
this.viewManager = new AccessibleViewManager(this.viewManagerConfig);
}
[Test]
public void ViewManagerConfigRejectsNullViewAssemblies()
{
var config = new ViewManagerConfig();
Assert.Throws<ArgumentNullException>(() => config.ViewAssemblies = null);
}
[Test]
public void ViewManagerConfigRejectsNullNamespaceTransformations()
{
var config = new ViewManagerConfig();
Assert.Throws<ArgumentNullException>(() => config.NamespaceTransformations = null);
}
[Test]
public void ViewManagerRejectsNullViewFactory()
{
var config = new ViewManagerConfig();
Assert.Throws<ArgumentNullException>(() => new ViewManager(config));
}
[Test]
public void OnModelChangedDoesNothingIfNoChange()
{
@ -327,8 +348,6 @@ namespace StyletUnitTests
model.Verify(x => x.AttachView(view));
}
[Test]
public void ViewNameResolutionWorksAsExpected()
{
@ -348,5 +367,25 @@ namespace StyletUnitTests
Assert.AreEqual("ViewModels.TestView", viewManager.ViewTypeNameForModelTypeName("ViewModels.TestViewModel"));
}
[Test]
public void NamespaceTransformationsTransformsNamespace()
{
this.viewManagerConfig.NamespaceTransformations["Foo.Bar"] = "Baz.Yay";
var viewManager = new AccessibleViewManager(this.viewManagerConfig);
Assert.AreEqual("Baz.Yay.ThingView", viewManager.ViewTypeNameForModelTypeName("Foo.Bar.ThingViewModel"));
Assert.AreEqual("Baz.Yay.Thing", viewManager.ViewTypeNameForModelTypeName("Foo.Bar.Thing"));
}
[Test]
public void NamespaceTransformationsTransformOnlyFirstMatch()
{
this.viewManagerConfig.NamespaceTransformations["Foo.Bar"] = "Baz.Yay";
this.viewManagerConfig.NamespaceTransformations["Baz.Yay"] = "One.Two";
Assert.AreEqual("Baz.Yay.ThingView", viewManager.ViewTypeNameForModelTypeName("Foo.Bar.ThingViewModel"));
Assert.AreEqual("One.Two.ThingView", viewManager.ViewTypeNameForModelTypeName("Baz.Yay.ThingViewModel"));
}
}
}