diff --git a/Stylet/Bootstrapper.cs b/Stylet/Bootstrapper.cs index 170a85a..bac7fd0 100644 --- a/Stylet/Bootstrapper.cs +++ b/Stylet/Bootstrapper.cs @@ -30,9 +30,9 @@ namespace Stylet var builder = new StyletIoCBuilder(); // Mark these as auto-bindings, so the user can replace them if they want - builder.Bind(typeof(IWindowManager), true).To().InSingletonScope(); - builder.Bind(typeof(IEventAggregator), true).To().InSingletonScope(); - builder.Bind(typeof(IViewManager), true).To().InSingletonScope(); + builder.BindWeak(typeof(IWindowManager)).To().InSingletonScope(); + builder.BindWeak(typeof(IEventAggregator)).To().InSingletonScope(); + builder.BindWeak(typeof(IViewManager)).To().InSingletonScope(); this.ConfigureIoC(builder); diff --git a/Stylet/StyletIoC/IRegistration.cs b/Stylet/StyletIoC/IRegistration.cs index 50b8790..1b464f1 100644 --- a/Stylet/StyletIoC/IRegistration.cs +++ b/Stylet/StyletIoC/IRegistration.cs @@ -11,7 +11,6 @@ namespace StyletIoC internal interface IRegistration { Type Type { get; } - bool WasAutoCreated { get; set; } Func GetGenerator(); Expression GetInstanceExpression(); } @@ -21,7 +20,6 @@ namespace StyletIoC protected ICreator creator; public Type Type { get { return this.creator.Type; } } - public bool WasAutoCreated { get; set; } protected Func generator { get; set; } @@ -97,7 +95,6 @@ namespace StyletIoC public string Key { get; set; } public Type Type { get; private set; } - public bool WasAutoCreated { get; set; } private Expression expression; private Func generator; diff --git a/Stylet/StyletIoC/IRegistrationCollection.cs b/Stylet/StyletIoC/IRegistrationCollection.cs index dd53d8b..c4b1e31 100644 --- a/Stylet/StyletIoC/IRegistrationCollection.cs +++ b/Stylet/StyletIoC/IRegistrationCollection.cs @@ -34,12 +34,7 @@ namespace StyletIoC public IRegistrationCollection AddRegistration(IRegistration registration) { - // If we were auto-created, and the newcomer is not, replace us with them - // This allows an explicit binding to replace an auto-created one - if (this.registration.WasAutoCreated && !registration.WasAutoCreated) - return new SingleRegistration(registration); - else - return new RegistrationCollection(new List() { this.registration, registration }); + return new RegistrationCollection(new List() { this.registration, registration }); } } @@ -70,14 +65,8 @@ namespace StyletIoC lock (this.registrations) { // Is there an existing registration for this type? - var existingRegistration = this.registrations.FirstOrDefault(x => x.Type == registration.Type); - if (existingRegistration != null) - { - if (existingRegistration.WasAutoCreated) - this.registrations.Remove(existingRegistration); - else - throw new StyletIoCRegistrationException(String.Format("Multiple registrations for type {0} found.", registration.Type.Name)); - } + if (this.registrations.Any(x => x.Type == registration.Type)) + throw new StyletIoCRegistrationException(String.Format("Multiple registrations for type {0} found.", registration.Type.Name)); this.registrations.Add(registration); return this; } diff --git a/Stylet/StyletIoC/StyletIoCBuilder.cs b/Stylet/StyletIoC/StyletIoCBuilder.cs index fb43ec1..ff2bdcd 100644 --- a/Stylet/StyletIoC/StyletIoCBuilder.cs +++ b/Stylet/StyletIoC/StyletIoCBuilder.cs @@ -76,19 +76,20 @@ namespace StyletIoC internal class BuilderBindTo : IBindTo { - private Type serviceType; + public Type ServiceType { get; private set; } private BuilderBindingBase builderBinding; - private bool wasAutoCreated; + public bool IsWeak { get; private set; } + public string Key { get { return this.builderBinding.Key; } } - public BuilderBindTo(Type serviceType, bool wasAutoCreated) + public BuilderBindTo(Type serviceType, bool isWeak) { - this.serviceType = serviceType; - this.wasAutoCreated = wasAutoCreated; + this.ServiceType = serviceType; + this.IsWeak = isWeak; } public IInScopeOrWithKey ToSelf() { - return this.To(this.serviceType); + return this.To(this.ServiceType); } public IInScopeOrWithKey To() @@ -98,19 +99,19 @@ namespace StyletIoC public IInScopeOrWithKey To(Type implementationType) { - this.builderBinding = new BuilderTypeBinding(this.serviceType, implementationType) { WasAutoCreated = this.wasAutoCreated }; + this.builderBinding = new BuilderTypeBinding(this.ServiceType, implementationType); return this.builderBinding; } public IInScopeOrWithKey ToFactory(Func factory) { - this.builderBinding = new BuilderFactoryBinding(this.serviceType, factory) { WasAutoCreated = this.wasAutoCreated }; + this.builderBinding = new BuilderFactoryBinding(this.ServiceType, factory); return this.builderBinding; } public IWithKey ToAbstractFactory() { - this.builderBinding = new AbstractFactoryBinding(this.serviceType) { WasAutoCreated = this.wasAutoCreated }; + this.builderBinding = new AbstractFactoryBinding(this.ServiceType); return this.builderBinding; } @@ -118,7 +119,7 @@ namespace StyletIoC { if (assemblies == null || assemblies.Length == 0) assemblies = new[] { Assembly.GetCallingAssembly() }; - this.builderBinding = new BuilderToAllImplementationsBinding(this.serviceType, assemblies) { WasAutoCreated = true }; + this.builderBinding = new BuilderToAllImplementationsBinding(this.ServiceType, assemblies); return this.builderBinding; } @@ -130,11 +131,9 @@ namespace StyletIoC internal abstract class BuilderBindingBase : IInScopeOrWithKey, IWithKey { - public bool WasAutoCreated { get; set; } - protected Type serviceType; protected bool isSingleton; - protected string key; + public string Key { get; protected set; } public BuilderBindingBase(Type serviceType) { @@ -148,7 +147,7 @@ namespace StyletIoC IInScope IInScopeOrWithKey.WithKey(string key) { - this.key = key; + this.Key = key; return this; } @@ -187,21 +186,20 @@ namespace StyletIoC if (this.serviceType.IsGenericTypeDefinition) { var unboundGeneric = new UnboundGeneric(implementationType, container, this.isSingleton); - container.AddUnboundGeneric(new TypeKey(serviceType, key), unboundGeneric); + container.AddUnboundGeneric(new TypeKey(serviceType, Key), unboundGeneric); } else { var creator = new TypeCreator(implementationType, container); IRegistration registration = this.isSingleton ? (IRegistration)new SingletonRegistration(creator) : (IRegistration)new TransientRegistration(creator); - registration.WasAutoCreated = this.WasAutoCreated; - container.AddRegistration(new TypeKey(this.serviceType, this.key ?? creator.AttributeKey), registration); + container.AddRegistration(new TypeKey(this.serviceType, this.Key ?? creator.AttributeKey), registration); } } void IWithKey.WithKey(string key) { - this.key = key; + this.Key = key; } public abstract void Build(StyletIoCContainer container); @@ -239,9 +237,8 @@ namespace StyletIoC { var creator = new FactoryCreator(this.factory, container); IRegistration registration = this.isSingleton ? (IRegistration)new SingletonRegistration(creator) : (IRegistration)new TransientRegistration(creator); - registration.WasAutoCreated = this.WasAutoCreated; - container.AddRegistration(new TypeKey(this.serviceType, this.key), registration); + container.AddRegistration(new TypeKey(this.serviceType, this.Key), registration); } } @@ -285,9 +282,8 @@ namespace StyletIoC var factoryType = container.GetFactoryForType(this.serviceType); var creator = new TypeCreator(factoryType, container); var registration = new SingletonRegistration(creator); - registration.WasAutoCreated = this.WasAutoCreated; - container.AddRegistration(new TypeKey(this.serviceType, this.key), registration); + container.AddRegistration(new TypeKey(this.serviceType, this.Key), registration); } } @@ -340,12 +336,17 @@ namespace StyletIoC /// Service to bind public IBindTo Bind(Type serviceType) { - return this.Bind(serviceType, false); + return this.BindInternal(serviceType, false); } - internal IBindTo Bind(Type serviceType, bool isAutoBinding) + internal IBindTo BindWeak(Type serviceType) { - var builderBindTo = new BuilderBindTo(serviceType, isAutoBinding); + return this.BindInternal(serviceType, true); + } + + internal IBindTo BindInternal(Type serviceType, bool isWeak) + { + var builderBindTo = new BuilderBindTo(serviceType, isWeak); this.bindings.Add(builderBindTo); return builderBindTo; } @@ -376,7 +377,7 @@ namespace StyletIoC // Don't care if binding fails - we're likely to hit a few of these try { - this.Bind(cls, true).To(cls); + this.BindWeak(cls).To(cls); } catch (StyletIoCRegistrationException e) { @@ -407,7 +408,10 @@ namespace StyletIoC container.AddRegistration(new TypeKey(typeof(IContainer), null), new SingletonRegistration(new FactoryCreator(c => container, container))); container.AddRegistration(new TypeKey(typeof(StyletIoCContainer), null), new SingletonRegistration(new FactoryCreator(c => container, container))); - foreach (var binding in this.bindings) + // For each TypeKey, we remove any weak bindings if there are any strong bindings + var groups = this.bindings.GroupBy(x => new { Key = x.Key, Type = x.ServiceType }); + var filtered = groups.SelectMany(group => group.Any(x => !x.IsWeak) ? group.Where(x => !x.IsWeak) : group); + foreach (var binding in filtered) { binding.Build(container); } diff --git a/Stylet/StyletIoC/StyletIoCContainer.cs b/Stylet/StyletIoC/StyletIoCContainer.cs index 58caa8a..d2e9c61 100644 --- a/Stylet/StyletIoC/StyletIoCContainer.cs +++ b/Stylet/StyletIoC/StyletIoCContainer.cs @@ -17,7 +17,8 @@ namespace StyletIoC /// /// Compile all known bindings (which would otherwise be compiled when needed), checking the dependency graph for consistency /// - void Compile(); + /// If true, throw if we fail to compile a type + void Compile(bool throwOnError = true); /// /// Fetch a single instance of the specified type @@ -121,7 +122,7 @@ namespace StyletIoC /// /// Compile all known bindings (which would otherwise be compiled when needed), checking the dependency graph for consistency /// - public void Compile() + public void Compile(bool throwOnError = true) { foreach (var kvp in this.registrations) { @@ -133,10 +134,8 @@ namespace StyletIoC } catch (StyletIoCFindConstructorException) { - // If we can't resolve an auto-created type, that's fine - // Don't remove it from the list of types - that way they'll get a - // decent error message if they actually try and resolve it - if (!registration.WasAutoCreated) + // If they've asked us to be quiet, we will + if (throwOnError) throw; } } @@ -414,14 +413,8 @@ namespace StyletIoC lock (unboundGenerics) { // Is there an auto-registration for this type? If so, remove it - var existingEntry = unboundGenerics.Where(x => x.Type == unboundGeneric.Type).FirstOrDefault(); - if (existingEntry != null) - { - if (existingEntry.WasAutoCreated) - unboundGenerics.Remove(existingEntry); - else - throw new StyletIoCRegistrationException(String.Format("Multiple registrations for type {0} found", typeKey.Type.Name)); - } + if (unboundGenerics.Any(x => x.Type == unboundGeneric.Type)) + throw new StyletIoCRegistrationException(String.Format("Multiple registrations for type {0} found", typeKey.Type.Name)); unboundGenerics.Add(unboundGeneric); } diff --git a/Stylet/StyletIoC/UnboundGeneric.cs b/Stylet/StyletIoC/UnboundGeneric.cs index 864d4a5..5cd1751 100644 --- a/Stylet/StyletIoC/UnboundGeneric.cs +++ b/Stylet/StyletIoC/UnboundGeneric.cs @@ -10,7 +10,6 @@ namespace StyletIoC internal class UnboundGeneric { private StyletIoCContainer container; - public bool WasAutoCreated { get; set; } public string Key { get; set; } public Type Type { get; private set; } public int NumTypeParams @@ -28,9 +27,9 @@ namespace StyletIoC public IRegistration CreateRegistrationForType(Type boundType) { if (this.IsSingleton) - return new SingletonRegistration(new TypeCreator(boundType, this.container)) { WasAutoCreated = this.WasAutoCreated }; + return new SingletonRegistration(new TypeCreator(boundType, this.container)); else - return new TransientRegistration(new TypeCreator(boundType, this.container)) { WasAutoCreated = this.WasAutoCreated }; + return new TransientRegistration(new TypeCreator(boundType, this.container)); } } }