mirror of https://github.com/AMT-Cheif/Stylet.git
Throw (by default) if ToAllImplementations does not find any implementations
This will happen if someone takes a concrete class (with no subclasses), uses ToAllImplementations on it (and InSingletonScope), and wonders why the singleton registration didn't 'take': the ToAllImplementations didn't create any bindings, so we fell back to auto-binding the type
This commit is contained in:
parent
fc869b642a
commit
235504941f
|
@ -69,15 +69,17 @@ namespace StyletIoC
|
|||
/// Discover all implementations of the service in the specified assemblies / the current assembly, and bind those to the service
|
||||
/// </summary>
|
||||
/// <param name="assemblies">Assemblies to search. If empty / null, searches the current assembly</param>
|
||||
/// <param name="allowZeroImplementations">By default, ToAllImplementations will throw an exception if no implementations are found. Set this parameter to true to allow this case</param>
|
||||
/// <returns>Fluent interface to continue configuration</returns>
|
||||
IInScopeOrWithKeyOrAsWeakBinding ToAllImplementations(IEnumerable<Assembly> assemblies);
|
||||
IInScopeOrWithKeyOrAsWeakBinding ToAllImplementations(IEnumerable<Assembly> assemblies, bool allowZeroImplementations = false);
|
||||
|
||||
/// <summary>
|
||||
/// Discover all implementations of the service in the specified assemblies / the current assembly, and bind those to the service
|
||||
/// </summary>
|
||||
/// <param name="allowZeroImplementations">By default, ToAllImplementations will throw an exception if no implementations are found. Set this parameter to true to allow this case</param>
|
||||
/// <param name="assemblies">Assemblies to search. If empty / null, searches the current assembly</param>
|
||||
/// <returns>Fluent interface to continue configuration</returns>
|
||||
IInScopeOrWithKeyOrAsWeakBinding ToAllImplementations(params Assembly[] assemblies);
|
||||
IInScopeOrWithKeyOrAsWeakBinding ToAllImplementations(bool allowZeroImplementations = false, params Assembly[] assemblies);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -77,15 +77,15 @@ namespace StyletIoC.Internal.Builders
|
|||
return this.builderBinding;
|
||||
}
|
||||
|
||||
public IInScopeOrWithKeyOrAsWeakBinding ToAllImplementations(IEnumerable<Assembly> assemblies)
|
||||
public IInScopeOrWithKeyOrAsWeakBinding ToAllImplementations(IEnumerable<Assembly> assemblies, bool allowZeroImplementations = false)
|
||||
{
|
||||
this.builderBinding = new BuilderToAllImplementationsBinding(this.ServiceTypes, this.getAssemblies(assemblies, "ToAllImplementations"));
|
||||
this.builderBinding = new BuilderToAllImplementationsBinding(this.ServiceTypes, this.getAssemblies(assemblies, "ToAllImplementations"), allowZeroImplementations);
|
||||
return this.builderBinding;
|
||||
}
|
||||
|
||||
public IInScopeOrWithKeyOrAsWeakBinding ToAllImplementations(params Assembly[] assemblies)
|
||||
public IInScopeOrWithKeyOrAsWeakBinding ToAllImplementations(bool allowZeroImplementations = false, params Assembly[] assemblies)
|
||||
{
|
||||
return this.ToAllImplementations(assemblies.AsEnumerable());
|
||||
return this.ToAllImplementations(assemblies.AsEnumerable(), allowZeroImplementations);
|
||||
}
|
||||
|
||||
internal void Build(Container container)
|
||||
|
|
|
@ -10,23 +10,31 @@ namespace StyletIoC.Internal.Builders
|
|||
internal class BuilderToAllImplementationsBinding : BuilderBindingBase
|
||||
{
|
||||
private readonly IEnumerable<Assembly> assemblies;
|
||||
private readonly bool allowZeroImplementations;
|
||||
|
||||
private BuilderTypeKey ServiceType { get { return this.ServiceTypes[0]; } }
|
||||
|
||||
public BuilderToAllImplementationsBinding(List<BuilderTypeKey> serviceTypes, IEnumerable<Assembly> assemblies)
|
||||
public BuilderToAllImplementationsBinding(List<BuilderTypeKey> serviceTypes, IEnumerable<Assembly> assemblies, bool allowZeroImplementations)
|
||||
: base(serviceTypes)
|
||||
{
|
||||
// This should be ensured by the fluent interfaces
|
||||
Trace.Assert(this.ServiceTypes.Count == 1);
|
||||
|
||||
this.assemblies = assemblies;
|
||||
this.allowZeroImplementations = allowZeroImplementations;
|
||||
}
|
||||
|
||||
public override void Build(Container container)
|
||||
{
|
||||
var candidates = from type in this.assemblies.Distinct().SelectMany(x => x.GetTypes())
|
||||
var candidates = (from type in this.assemblies.Distinct().SelectMany(x => x.GetTypes())
|
||||
let baseType = type.GetBaseTypesAndInterfaces().FirstOrDefault(x => x == this.ServiceType.Type || (x.IsGenericType && x.GetGenericTypeDefinition() == this.ServiceType.Type))
|
||||
where baseType != null
|
||||
select new { Type = type, Base = baseType.ContainsGenericParameters ? baseType.GetGenericTypeDefinition() : baseType };
|
||||
select new { Type = type, Base = baseType.ContainsGenericParameters ? baseType.GetGenericTypeDefinition() : baseType }).ToList();
|
||||
|
||||
if (!this.allowZeroImplementations && candidates.Count == 0)
|
||||
{
|
||||
throw new StyletIoCRegistrationException(String.Format("Did not find any implementations of the type {0}", this.ServiceType.Type));
|
||||
}
|
||||
|
||||
foreach (var candidate in candidates)
|
||||
{
|
||||
|
|
|
@ -26,6 +26,9 @@ namespace StyletUnitTests
|
|||
[Inject("Key")]
|
||||
class C4 { }
|
||||
|
||||
interface I5 { }
|
||||
class C5 { }
|
||||
|
||||
[Test]
|
||||
public void NongenericInterfaceToAllImplementations()
|
||||
{
|
||||
|
@ -162,5 +165,24 @@ namespace StyletUnitTests
|
|||
|
||||
Assert.IsInstanceOf<C11>(ioc.Get<C11>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToAllImplementationsThrowsIfNoImplementationsFound()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<I5>().ToAllImplementations();
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => builder.BuildContainer());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToAllImplementationsDoesNotThrowIfNoImplementationsFoundAndAllowZeroImplementationsIsTrue()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<I5>().ToAllImplementations(allowZeroImplementations: true);
|
||||
IContainer ioc = null;
|
||||
Assert.DoesNotThrow(() => ioc = builder.BuildContainer());
|
||||
|
||||
Assert.DoesNotThrow(() => ioc.GetAll<I5>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue