mirror of https://github.com/AMT-Cheif/Stylet.git
GetAll returns empty enumerable if no registrations found
This commit is contained in:
parent
26116cb528
commit
142fb40ed9
|
@ -64,6 +64,7 @@
|
|||
<Compile Include="StyletIoC\Internal\Creators\TypeCreator.cs" />
|
||||
<Compile Include="StyletIoC\Internal\DelegatingDictionary.cs" />
|
||||
<Compile Include="StyletIoC\Creation\IRegistrationContext.cs" />
|
||||
<Compile Include="StyletIoC\Internal\RegistrationCollections\EmptyRegistrationCollection.cs" />
|
||||
<Compile Include="StyletIoC\Internal\RegistrationCollections\RegistrationCollection.cs" />
|
||||
<Compile Include="StyletIoC\Internal\RegistrationCollections\SingleRegistration.cs" />
|
||||
<Compile Include="StyletIoC\Internal\Registrations\FuncNoKeyRegistration.cs" />
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace StyletIoC.Creation
|
|||
IRegistration GetSingleRegistration(Type type, string key, bool searchGetAllTypes);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve all IRegistrations for the type+key combination, or throw an exception if there are none
|
||||
/// Retrieve all IRegistrations for the type+key combination
|
||||
/// </summary>
|
||||
/// <remarks>If a single registration exists, then the returned list will contain a single entry</remarks>
|
||||
/// <param name="type">Type to search for</param>
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace StyletIoC.Internal.Builders
|
|||
this.serviceType = serviceType;
|
||||
|
||||
// Default is transient
|
||||
this.registrationFactory = (ctx, creator, key) => new TransientRegistration(creator);
|
||||
this.registrationFactory = (ctx, service, creator, key) => new TransientRegistration(creator);
|
||||
}
|
||||
|
||||
IAsWeakBinding IInScopeOrAsWeakBinding.WithRegistrationFactory(RegistrationFactory registrationFactory)
|
||||
|
@ -71,7 +71,7 @@ namespace StyletIoC.Internal.Builders
|
|||
|
||||
if (serviceType.IsGenericTypeDefinition)
|
||||
{
|
||||
var unboundGeneric = new UnboundGeneric(implementationType, container, this.registrationFactory);
|
||||
var unboundGeneric = new UnboundGeneric(serviceType, implementationType, container, this.registrationFactory);
|
||||
container.AddUnboundGeneric(new TypeKey(serviceType, this.Key), unboundGeneric);
|
||||
}
|
||||
else
|
||||
|
@ -86,7 +86,7 @@ namespace StyletIoC.Internal.Builders
|
|||
// Convenience...
|
||||
protected IRegistration CreateRegistration(IRegistrationContext registrationContext, ICreator creator)
|
||||
{
|
||||
return this.registrationFactory(registrationContext, creator, this.Key);
|
||||
return this.registrationFactory(registrationContext, this.serviceType, creator, this.Key);
|
||||
}
|
||||
|
||||
IAsWeakBinding IWithKeyOrAsWeakBinding.WithKey(string key)
|
||||
|
|
|
@ -180,6 +180,8 @@ namespace StyletIoC.Internal
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Is it a 'get all' request?
|
||||
IRegistration registration;
|
||||
return this.TryRetrieveGetAllRegistration(typeKey, out registration);
|
||||
|
@ -192,7 +194,7 @@ namespace StyletIoC.Internal
|
|||
{
|
||||
Type type = typeKey.Type;
|
||||
// Elements are never removed from this.registrations, so we're safe to make this ContainsKey query
|
||||
if (!type.IsGenericType || type.GenericTypeArguments.Length != 1 || !this.CanResolve(new TypeKey(type.GenericTypeArguments[0], typeKey.Key)))
|
||||
if (!type.IsGenericType || !typeKey.Type.Implements(typeof(IEnumerable<>)))
|
||||
return null;
|
||||
return type.GenericTypeArguments[0];
|
||||
}
|
||||
|
@ -379,7 +381,8 @@ namespace StyletIoC.Internal
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new StyletIoCRegistrationException(String.Format("No registrations found for service {0}.", typeKey.Type.GetDescription()));
|
||||
// This will throw a StyletIoCRegistrationException is GetSingle is requested
|
||||
registrations = new EmptyRegistrationCollection(typeKey.Type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
using StyletIoC.Creation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletIoC.Internal.RegistrationCollections
|
||||
{
|
||||
internal class EmptyRegistrationCollection : IRegistrationCollection
|
||||
{
|
||||
private readonly Type type;
|
||||
|
||||
public EmptyRegistrationCollection(Type type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public IRegistration GetSingle()
|
||||
{
|
||||
throw new StyletIoCRegistrationException(String.Format("No registrations found for service {0}.", this.type.GetDescription()));
|
||||
}
|
||||
|
||||
public List<IRegistration> GetAll()
|
||||
{
|
||||
return new List<IRegistration>();
|
||||
}
|
||||
|
||||
public IRegistrationCollection AddRegistration(IRegistration registration)
|
||||
{
|
||||
return new SingleRegistration(registration);
|
||||
}
|
||||
|
||||
public IRegistrationCollection CloneToContext(IRegistrationContext context)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -52,10 +52,11 @@ namespace StyletIoC.Internal.Registrations
|
|||
if (this.expression != null)
|
||||
return this.expression;
|
||||
|
||||
var list = Expression.New(this.Type);
|
||||
var init = Expression.ListInit(list, this.parentContext.GetAllRegistrations(this.Type.GenericTypeArguments[0], this.Key, false).Select(x => x.GetInstanceExpression(registrationContext)));
|
||||
var listNew = Expression.New(this.Type);
|
||||
var instanceExpressions = this.parentContext.GetAllRegistrations(this.Type.GenericTypeArguments[0], this.Key, false).Select(x => x.GetInstanceExpression(registrationContext));
|
||||
Expression list = instanceExpressions.Any() ? (Expression)Expression.ListInit(listNew, instanceExpressions) : listNew;
|
||||
|
||||
Interlocked.CompareExchange(ref this.expression, init, null);
|
||||
Interlocked.CompareExchange(ref this.expression, list, null);
|
||||
return this.expression;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace StyletIoC.Internal.Registrations
|
|||
internal class PerContainerRegistration : RegistrationBase
|
||||
{
|
||||
private readonly IRegistrationContext parentContext;
|
||||
private readonly Type serviceType;
|
||||
private readonly string key;
|
||||
private readonly object instanceFactoryLock = new object();
|
||||
private Func<IRegistrationContext, object> instanceFactory;
|
||||
|
@ -20,10 +21,11 @@ namespace StyletIoC.Internal.Registrations
|
|||
|
||||
private static readonly MethodInfo getMethod = typeof(IContainer).GetMethod("Get", new[] { typeof(Type), typeof(string) });
|
||||
|
||||
public PerContainerRegistration(IRegistrationContext parentContext, ICreator creator, string key, Func<IRegistrationContext, object> instanceFactory = null)
|
||||
public PerContainerRegistration(IRegistrationContext parentContext, Type serviceType, ICreator creator, string key, Func<IRegistrationContext, object> instanceFactory = null)
|
||||
: base(creator)
|
||||
{
|
||||
this.parentContext = parentContext;
|
||||
this.serviceType = serviceType;
|
||||
this.key = key;
|
||||
this.instanceFactory = instanceFactory;
|
||||
|
||||
|
@ -71,7 +73,7 @@ namespace StyletIoC.Internal.Registrations
|
|||
public override Expression GetInstanceExpression(ParameterExpression registrationContext)
|
||||
{
|
||||
// Always synthesize into a method call onto the current context
|
||||
var call = Expression.Call(registrationContext, getMethod, Expression.Constant(this.Type), Expression.Constant(this.key, typeof(string)));
|
||||
var call = Expression.Call(registrationContext, getMethod, Expression.Constant(this.serviceType), Expression.Constant(this.key, typeof(string)));
|
||||
var cast = Expression.Convert(call, this.Type);
|
||||
return cast;
|
||||
}
|
||||
|
@ -80,7 +82,7 @@ namespace StyletIoC.Internal.Registrations
|
|||
{
|
||||
// Ensure the factory's created, and pass it down. This means the work of compiling the creation expression is done once, ever
|
||||
this.EnsureInstanceFactoryCreated();
|
||||
return new PerContainerRegistration(context, this.creator, this.key, this.instanceFactory);
|
||||
return new PerContainerRegistration(context, this.serviceType, this.creator, this.key, this.instanceFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ namespace StyletIoC.Internal
|
|||
public static bool Implements(this Type implementationType, Type serviceType)
|
||||
{
|
||||
return serviceType.IsAssignableFrom(implementationType) ||
|
||||
(implementationType.IsGenericType && serviceType.IsGenericTypeDefinition && serviceType.IsAssignableFrom(implementationType.GetGenericTypeDefinition())) ||
|
||||
implementationType.GetBaseTypesAndInterfaces().Any(x => x == serviceType || (x.IsGenericType && x.GetGenericTypeDefinition() == serviceType));
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,13 @@ namespace StyletIoC.Internal
|
|||
internal class UnboundGeneric
|
||||
{
|
||||
private IRegistrationContext parentContext;
|
||||
private readonly Type serviceType;
|
||||
public Type Type { get; private set; }
|
||||
public RegistrationFactory RegistrationFactory { get; private set; }
|
||||
|
||||
public UnboundGeneric(Type type, IRegistrationContext parentContext, RegistrationFactory registrationFactory)
|
||||
public UnboundGeneric(Type serviceType, Type type, IRegistrationContext parentContext, RegistrationFactory registrationFactory)
|
||||
{
|
||||
this.serviceType = serviceType;
|
||||
this.Type = type;
|
||||
this.parentContext = parentContext;
|
||||
this.RegistrationFactory = registrationFactory;
|
||||
|
@ -19,7 +21,7 @@ namespace StyletIoC.Internal
|
|||
|
||||
public IRegistration CreateRegistrationForTypeKey(TypeKey boundTypeKey)
|
||||
{
|
||||
return this.RegistrationFactory(this.parentContext, new TypeCreator(boundTypeKey.Type, this.parentContext), boundTypeKey.Key);
|
||||
return this.RegistrationFactory(this.parentContext, this.serviceType, new TypeCreator(boundTypeKey.Type, this.parentContext), boundTypeKey.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,11 +130,11 @@ namespace StyletUnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public void GetAllThrowsIfNoRegistrationsFound()
|
||||
public void GetAllDoesNotThrowIfNoRegistrationsFound()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
var ioc = builder.BuildContainer();
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => ioc.GetAll<IC1>());
|
||||
Assert.DoesNotThrow(() => ioc.GetAll<IC1>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
Loading…
Reference in New Issue