Remove AssemblySource, relying instead on a List<Assembly> on BootstrapperBase

This commit is contained in:
Antony Male 2014-11-30 14:58:04 +00:00
parent 0f93eb1832
commit a421fc6922
11 changed files with 44 additions and 98 deletions

View File

@ -1,17 +0,0 @@
using System;
using System.Reflection;
namespace Stylet
{
/// <summary>
/// Container for the list of assemblies in which Stylet will look for types
/// </summary>
public static class AssemblySource
{
/// <summary>
/// List of assemblies in which Stylet will look for types, (for autobinding in StyletIoC, and for finding Views).
/// Populated by the Bootstrapper
/// </summary>
public static readonly IObservableCollection<Assembly> Assemblies = new BindableCollection<Assembly>();
}
}

View File

@ -1,7 +1,6 @@
using StyletIoC;
using System;
using System.Collections.Generic;
using System.Windows;
namespace Stylet
{
@ -19,9 +18,10 @@ namespace Stylet
/// <summary>
/// Overridden from BootstrapperBase, this sets up the IoC container
/// </summary>
protected override void Configure()
protected override sealed void ConfigureBootstrapper()
{
base.Configure();
// This needs to be called before the container is set up, as it might affect the assemblies
this.Configure();
var builder = new StyletIoCBuilder();
@ -31,6 +31,11 @@ namespace Stylet
this.Container = builder.BuildContainer();
}
/// <summary>
/// Override to configure your IoC container, and anything else
/// </summary>
protected virtual void Configure() { }
/// <summary>
/// Carries out default configuration of StyletIoC. Override if you don't want to do this
/// </summary>
@ -38,12 +43,12 @@ namespace Stylet
protected virtual void DefaultConfigureIoC(StyletIoCBuilder builder)
{
// Mark these as auto-bindings, so the user can replace them if they want
builder.Bind<IViewManager>().ToInstance(new ViewManager(type => this.Container.Get(type) as UIElement)).AsWeakBinding();
builder.Bind<IViewManager>().ToInstance(new ViewManager(this.Assemblies, type => this.Container.Get(type))).AsWeakBinding();
builder.Bind<IWindowManager>().To<WindowManager>().InSingletonScope().AsWeakBinding();
builder.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope().AsWeakBinding();
builder.Bind<IMessageBoxViewModel>().To<MessageBoxViewModel>().AsWeakBinding();
builder.Autobind(AssemblySource.Assemblies);
builder.Autobind(this.Assemblies);
}
/// <summary>

View File

@ -20,6 +20,20 @@ namespace Stylet
/// </summary>
protected Application Application { get; private set; }
/// <summary>
/// Assemblies which are used for IoC container auto-binding and searching for Views.
/// Set this in Configure() if you want to override it
/// </summary>
protected List<Assembly> Assemblies { get; set; }
/// <summary>
/// Instantiate a new BootstrapperBase
/// </summary>
public BootstrapperBase()
{
this.Assemblies = new List<Assembly>() { typeof(BootstrapperBase<>).Assembly, this.GetType().Assembly };
}
/// <summary>
/// Called by the ApplicationLoader when this bootstrapper is loaded
/// </summary>
@ -50,12 +64,7 @@ namespace Stylet
// Use the current SynchronizationContext for the Execute helper
Execute.Dispatcher = new DispatcherWrapper(Dispatcher.CurrentDispatcher);
// Add the current assembly to the assemblies list - this will be needed by the IViewManager
// However it must be done *after* the SynchronizationContext has been set, or we'll try to raise a PropertyChanged notification and fail
AssemblySource.Assemblies.Clear();
AssemblySource.Assemblies.AddRange(this.SelectAssemblies());
this.Configure();
this.ConfigureBootstrapper();
View.ViewManager = this.GetInstance<IViewManager>();
@ -76,7 +85,7 @@ namespace Stylet
/// <summary>
/// Override to configure your IoC container, and anything else
/// </summary>
protected virtual void Configure() { }
protected virtual void ConfigureBootstrapper() { }
/// <summary>
/// Given a type, use the IoC container to fetch an instance of it
@ -85,15 +94,6 @@ namespace Stylet
/// <returns>Fetched instance</returns>
protected abstract T GetInstance<T>();
/// <summary>
/// Initial contents of AssemblySource.Assemblies, defaults to the entry assembly
/// </summary>
/// <returns></returns>
protected virtual IEnumerable<Assembly> SelectAssemblies()
{
return new[] { typeof(BootstrapperBase<>).Assembly, this.GetType().Assembly };
}
/// <summary>
/// Hook called on application startup. This occurs before Start() is called (if autoStart is true)
/// </summary>

View File

@ -95,7 +95,6 @@
<Compile Include="StyletIoC\Internal\TypeExtensions.cs" />
<Compile Include="ValidatingModelBase.cs" />
<Compile Include="Xaml\ActionExtension.cs" />
<Compile Include="AssemblySource.cs" />
<Compile Include="BindableCollection.cs" />
<Compile Include="BootstrapperBase.cs" />
<Compile Include="Xaml\BoolToVisibilityConverter.cs" />

View File

@ -1,6 +1,7 @@
using Stylet.Logging;
using Stylet.Xaml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
@ -35,14 +36,17 @@ namespace Stylet
public class ViewManager : IViewManager
{
private static readonly ILogger logger = LogManager.GetLogger(typeof(ViewManager));
private readonly Func<Type, UIElement> viewFactory;
private readonly List<Assembly> assemblies;
private readonly Func<Type, object> viewFactory;
/// <summary>
/// Create a new ViewManager, with the given viewFactory
/// </summary>
/// <param name="assemblies">Assemblies to search for View types in</param>
/// <param name="viewFactory">Delegate used to create view instances from their type</param>
public ViewManager(Func<Type, UIElement> viewFactory)
public ViewManager(List<Assembly> assemblies, Func<Type, object> viewFactory)
{
this.assemblies = assemblies;
this.viewFactory = viewFactory;
}
@ -103,7 +107,7 @@ namespace Stylet
protected virtual Type ViewTypeForViewName(string viewName)
{
// TODO: This might need some more thinking
var viewType = AssemblySource.Assemblies.SelectMany(x => x.GetExportedTypes()).FirstOrDefault(x => x.FullName == viewName);
var viewType = this.assemblies.SelectMany(x => x.GetExportedTypes()).FirstOrDefault(x => x.FullName == viewName);
if (viewType == null)
{
var e = new StyletViewLocationException(String.Format("Unable to find a View with type {0}", viewName), viewName);
@ -145,7 +149,7 @@ namespace Stylet
throw e;
}
var view = this.viewFactory(viewType);
var view = this.viewFactory(viewType) as UIElement;
// If it doesn't have a code-behind, this won't be called
var initializer = viewType.GetMethod("InitializeComponent", BindingFlags.Public | BindingFlags.Instance);

View File

@ -14,7 +14,6 @@ namespace StyletIntegrationTests
{
protected override void Configure()
{
base.Configure();
LogManager.Enabled = true;
}

View File

@ -1,30 +0,0 @@
using NUnit.Framework;
using Stylet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace StyletUnitTests
{
[TestFixture]
public class AssemblySourceTests
{
[TestFixtureSetUp]
public void SetUpFixture()
{
Execute.TestExecuteSynchronously = true;
AssemblySource.Assemblies.Clear();
}
[Test]
public void TestAssemblies()
{
var assembly = Assembly.GetExecutingAssembly();
AssemblySource.Assemblies.Add(assembly);
CollectionAssert.AreEqual(AssemblySource.Assemblies, new[] { assembly });
}
}
}

View File

@ -56,10 +56,10 @@ namespace StyletUnitTests
}
public bool ConfigureCalled;
protected override void Configure()
protected override void ConfigureBootstrapper()
{
this.ConfigureCalled = true;
base.Configure();
base.ConfigureBootstrapper();
}
public new void Start()
@ -77,7 +77,6 @@ namespace StyletUnitTests
public void FixtureSetUp()
{
Execute.TestExecuteSynchronously = true;
AssemblySource.Assemblies.Clear();
}
[SetUp]
@ -96,14 +95,6 @@ namespace StyletUnitTests
Assert.NotNull(Execute.Dispatcher); // Can't test any further, unfortunately
}
[Test]
public void StartSetsUpAssemblySource()
{
AssemblySource.Assemblies.Add(null);
this.bootstrapper.Start();
Assert.That(AssemblySource.Assemblies, Is.EquivalentTo(new[] { typeof(BootstrapperBase<>).Assembly, this.bootstrapper.GetType().Assembly }));
}
[Test]
public void StartCallsConfigure()
{

View File

@ -29,7 +29,7 @@ namespace StyletUnitTests
public new void Configure()
{
base.Configure();
base.ConfigureBootstrapper();
}
public bool ConfigureIoCCalled;
@ -52,7 +52,6 @@ namespace StyletUnitTests
public void FixtureSetUp()
{
Execute.TestExecuteSynchronously = true;
AssemblySource.Assemblies.Clear();
}
[SetUp]
@ -64,7 +63,6 @@ namespace StyletUnitTests
[Test]
public void ConfigureBindsRequiredTypes()
{
AssemblySource.Assemblies.Add(this.GetType().Assembly);
this.bootstrapper.Configure();
var ioc = this.bootstrapper.Container;
@ -79,7 +77,6 @@ namespace StyletUnitTests
[Test]
public void ConfigureCallsConfigureIoCWithCorrectBuilder()
{
AssemblySource.Assemblies.Add(this.GetType().Assembly);
this.bootstrapper.Configure();
var ioc = this.bootstrapper.Container;

View File

@ -54,7 +54,6 @@
<ItemGroup>
<Compile Include="ActionExtensionTests.cs" />
<Compile Include="ApplicationLoaderTests.cs" />
<Compile Include="AssemblySourceTests.cs" />
<Compile Include="BindableCollectionTests.cs" />
<Compile Include="BoolToVisibilityConverterTests.cs" />
<Compile Include="BootstrapperBaseTests.cs" />

View File

@ -30,7 +30,7 @@ namespace StyletUnitTests
private class AccessibleViewManager : ViewManager
{
public AccessibleViewManager() : base(null) { }
public AccessibleViewManager() : base(new List<Assembly>(), null) { }
public new UIElement CreateViewForModel(object model)
{
@ -48,7 +48,7 @@ namespace StyletUnitTests
public UIElement View;
public object RequestedModel;
public CreatingAndBindingViewManager() : base(null) { }
public CreatingAndBindingViewManager() : base(new List<Assembly>(), null) { }
protected override UIElement CreateViewForModel(object model)
{
@ -67,7 +67,7 @@ namespace StyletUnitTests
private class LocatingViewManager : ViewManager
{
public LocatingViewManager(Func<Type, UIElement> viewFactory) : base(viewFactory) { }
public LocatingViewManager(Func<Type, UIElement> viewFactory) : base(new List<Assembly>(), viewFactory) { }
public Type LocatedViewType;
protected override Type LocateViewForModel(Type modelType)
@ -88,7 +88,7 @@ namespace StyletUnitTests
private class MyViewManager : ViewManager
{
public MyViewManager() : base(null) { }
public MyViewManager(List<Assembly> assemblies) : base(assemblies, null) { }
public new Type LocateViewForModel(Type modelType)
{
@ -102,13 +102,12 @@ namespace StyletUnitTests
public void FixtureSetUp()
{
Execute.TestExecuteSynchronously = true;
AssemblySource.Assemblies.Clear();
}
[SetUp]
public void SetUp()
{
this.viewManager = new MyViewManager();
this.viewManager = new MyViewManager(new List<Assembly>());
}
[Test]
@ -166,9 +165,9 @@ namespace StyletUnitTests
[Test]
public void LocateViewForModelFindsViewForModel()
{
var viewManager = new MyViewManager(new List<Assembly>() { Assembly.GetExecutingAssembly() });
Execute.TestExecuteSynchronously = true;
AssemblySource.Assemblies.Add(Assembly.GetExecutingAssembly());
var viewType = this.viewManager.LocateViewForModel(typeof(ViewManagerTestsViewModel));
var viewType = viewManager.LocateViewForModel(typeof(ViewManagerTestsViewModel));
Assert.AreEqual(typeof(ViewManagerTestsView), viewType);
}