mirror of https://github.com/AMT-Cheif/Stylet.git
Little bit of work on the unit test coverage
This commit is contained in:
parent
95e52d543d
commit
3887d38a4a
|
@ -82,10 +82,7 @@ namespace StyletIoC
|
||||||
|
|
||||||
private string KeyForParameter(ParameterInfo parameter)
|
private string KeyForParameter(ParameterInfo parameter)
|
||||||
{
|
{
|
||||||
var attributes = parameter.GetCustomAttributes(typeof(InjectAttribute));
|
var attribute = parameter.GetCustomAttributes(typeof(InjectAttribute)).FirstOrDefault() as InjectAttribute;
|
||||||
if (attributes == null)
|
|
||||||
return null;
|
|
||||||
var attribute = (InjectAttribute)attributes.FirstOrDefault();
|
|
||||||
return attribute == null ? null : attribute.Key;
|
return attribute == null ? null : attribute.Key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
@ -133,9 +134,10 @@ namespace StyletIoC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class PerContainerRegistrations : RegistrationBase
|
internal class PerContainerRegistration : RegistrationBase
|
||||||
{
|
{
|
||||||
private readonly IRegistrationContext parentContext;
|
private readonly IRegistrationContext parentContext;
|
||||||
|
private readonly string key;
|
||||||
private readonly object instanceFactoryLock = new object();
|
private readonly object instanceFactoryLock = new object();
|
||||||
private Func<IRegistrationContext, object> instanceFactory;
|
private Func<IRegistrationContext, object> instanceFactory;
|
||||||
private object instance;
|
private object instance;
|
||||||
|
@ -143,10 +145,11 @@ namespace StyletIoC
|
||||||
|
|
||||||
private static readonly MethodInfo getMethod = typeof(IContainer).GetMethod("Get", new[] { typeof(Type), typeof(string) });
|
private static readonly MethodInfo getMethod = typeof(IContainer).GetMethod("Get", new[] { typeof(Type), typeof(string) });
|
||||||
|
|
||||||
public PerContainerRegistrations(IRegistrationContext parentContext, ICreator creator, Func<IRegistrationContext, object> instanceFactory = null)
|
public PerContainerRegistration(IRegistrationContext parentContext, ICreator creator, string key, Func<IRegistrationContext, object> instanceFactory = null)
|
||||||
: base(creator)
|
: base(creator)
|
||||||
{
|
{
|
||||||
this.parentContext = parentContext;
|
this.parentContext = parentContext;
|
||||||
|
this.key = key;
|
||||||
this.instanceFactory = instanceFactory;
|
this.instanceFactory = instanceFactory;
|
||||||
|
|
||||||
this.parentContext.Disposing += (o, e) =>
|
this.parentContext.Disposing += (o, e) =>
|
||||||
|
@ -177,34 +180,28 @@ namespace StyletIoC
|
||||||
protected override Func<IRegistrationContext, object> GetGeneratorInternal()
|
protected override Func<IRegistrationContext, object> GetGeneratorInternal()
|
||||||
{
|
{
|
||||||
// If the context is our parent context, then everything's fine and we can return our instance
|
// If the context is our parent context, then everything's fine and we can return our instance
|
||||||
// If not, we need to call Get on the current context, and a different instance of us will be invoked again by that
|
// If not, well, this should never happen. When we're cloned to the new context, we set ourselves up with the new parent
|
||||||
return ctx =>
|
return ctx =>
|
||||||
{
|
{
|
||||||
if (ctx != this.parentContext)
|
Debug.Assert(ctx == this.parentContext);
|
||||||
{
|
if (this.disposed)
|
||||||
return ctx.Get(this.Type);
|
throw new ObjectDisposedException(String.Format("ChildContainer registration for type {0}", this.Type.Description()));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (this.disposed)
|
|
||||||
throw new ObjectDisposedException(String.Format("ChildContainer registration for type {0}", this.Type.Description()));
|
|
||||||
|
|
||||||
if (this.instance != null)
|
if (this.instance != null)
|
||||||
return this.instance;
|
|
||||||
|
|
||||||
this.EnsureInstanceFactoryCreated();
|
|
||||||
|
|
||||||
var instance = this.instanceFactory(ctx);
|
|
||||||
Interlocked.CompareExchange(ref this.instance, instance, null);
|
|
||||||
return this.instance;
|
return this.instance;
|
||||||
}
|
|
||||||
|
this.EnsureInstanceFactoryCreated();
|
||||||
|
|
||||||
|
var instance = this.instanceFactory(ctx);
|
||||||
|
Interlocked.CompareExchange(ref this.instance, instance, null);
|
||||||
|
return this.instance;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Expression GetInstanceExpression(ParameterExpression registrationContext)
|
public override Expression GetInstanceExpression(ParameterExpression registrationContext)
|
||||||
{
|
{
|
||||||
// Always synthesize into a method call onto the current context
|
// Always synthesize into a method call onto the current context
|
||||||
var call = Expression.Call(registrationContext, getMethod, Expression.Constant(this.Type));
|
var call = Expression.Call(registrationContext, getMethod, Expression.Constant(this.Type), Expression.Constant(this.key, typeof(string)));
|
||||||
var cast = Expression.Convert(call, this.Type);
|
var cast = Expression.Convert(call, this.Type);
|
||||||
return cast;
|
return cast;
|
||||||
}
|
}
|
||||||
|
@ -213,7 +210,7 @@ namespace StyletIoC
|
||||||
{
|
{
|
||||||
// Ensure the factory's created, and pass it down. This means the work of compiling the creation expression is done once, ever
|
// Ensure the factory's created, and pass it down. This means the work of compiling the creation expression is done once, ever
|
||||||
this.EnsureInstanceFactoryCreated();
|
this.EnsureInstanceFactoryCreated();
|
||||||
return new PerContainerRegistrations(context, this.creator, this.instanceFactory);
|
return new PerContainerRegistration(context, this.creator, this.key, this.instanceFactory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +343,7 @@ namespace StyletIoC
|
||||||
|
|
||||||
public IRegistration CloneToContext(IRegistrationContext context)
|
public IRegistration CloneToContext(IRegistrationContext context)
|
||||||
{
|
{
|
||||||
return this;
|
throw new InvalidOperationException("should not be cloned");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace StyletIoC
|
||||||
|
|
||||||
public static void InPerContainerScope(this IInScope builder)
|
public static void InPerContainerScope(this IInScope builder)
|
||||||
{
|
{
|
||||||
builder.WithRegistrationFactory((ctx, creator, key) => new PerContainerRegistrations(ctx, creator));
|
builder.WithRegistrationFactory((ctx, creator, key) => new PerContainerRegistration(ctx, creator, key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ namespace StyletUnitTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void CreatingSameBindingOnParentAndChildCausesMultipleRegistrations()
|
public void CreatingSameBindingOnParentAndChildCausesMultipleRegistrations_1()
|
||||||
{
|
{
|
||||||
var builder = new StyletIoCBuilder();
|
var builder = new StyletIoCBuilder();
|
||||||
builder.Bind<I1>().To<C11>();
|
builder.Bind<I1>().To<C11>();
|
||||||
|
@ -146,8 +146,8 @@ namespace StyletUnitTests
|
||||||
|
|
||||||
var r = child.GetAll<I1>();
|
var r = child.GetAll<I1>();
|
||||||
|
|
||||||
Assert.AreEqual(2, child.GetAll<I1>().Count());
|
|
||||||
Assert.AreEqual(1, parent.GetAll<I1>().Count());
|
Assert.AreEqual(1, parent.GetAll<I1>().Count());
|
||||||
|
Assert.AreEqual(2, child.GetAll<I1>().Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -264,6 +264,20 @@ namespace StyletUnitTests
|
||||||
Assert.AreNotEqual(parent.Get<C1>(), child.Get<C1>());
|
Assert.AreNotEqual(parent.Get<C1>(), child.Get<C1>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void KeyedChildContainerScopeHasOneInstancePerScope()
|
||||||
|
{
|
||||||
|
var builder = new StyletIoCBuilder();
|
||||||
|
builder.Bind<C1>().ToSelf().WithKey("foo").InPerContainerScope();
|
||||||
|
var parent = builder.BuildContainer();
|
||||||
|
|
||||||
|
var child = parent.CreateChildBuilder().BuildContainer();
|
||||||
|
|
||||||
|
Assert.AreEqual(parent.Get<C1>("foo"), parent.Get<C1>("foo"));
|
||||||
|
Assert.AreEqual(child.Get<C1>("foo"), child.Get<C1>("foo"));
|
||||||
|
Assert.AreNotEqual(parent.Get<C1>("foo"), child.Get<C1>("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ChildContainerScopeDisposalDisposesCorrectThing()
|
public void ChildContainerScopeDisposalDisposesCorrectThing()
|
||||||
{
|
{
|
||||||
|
@ -281,5 +295,48 @@ namespace StyletUnitTests
|
||||||
Assert.True(childs.Disposed);
|
Assert.True(childs.Disposed);
|
||||||
Assert.False(parents.Disposed);
|
Assert.False(parents.Disposed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void UsingPerContainerRegistrationAfterDisposalPromptsException()
|
||||||
|
{
|
||||||
|
var builder = new StyletIoCBuilder();
|
||||||
|
builder.Bind<C1>().ToSelf().InPerContainerScope();
|
||||||
|
var ioc = builder.BuildContainer();
|
||||||
|
|
||||||
|
ioc.Dispose();
|
||||||
|
Assert.Throws<ObjectDisposedException>(() => ioc.Get<C1>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncFactoryFetchesInstanceFromCorrectChild()
|
||||||
|
{
|
||||||
|
var builder = new StyletIoCBuilder();
|
||||||
|
builder.Bind<C1>().ToSelf().InPerContainerScope();
|
||||||
|
var parent = builder.BuildContainer();
|
||||||
|
|
||||||
|
var child = parent.CreateChildBuilder().BuildContainer();
|
||||||
|
|
||||||
|
var funcFromParent = parent.Get<Func<C1>>();
|
||||||
|
var funcFromChild = child.Get<Func<C1>>();
|
||||||
|
|
||||||
|
Assert.AreEqual(parent.Get<C1>(), funcFromParent());
|
||||||
|
Assert.AreEqual(child.Get<C1>(), funcFromChild());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FuncFactoryWithKeyFetchesInstanceFromCorrectChild()
|
||||||
|
{
|
||||||
|
var builder = new StyletIoCBuilder();
|
||||||
|
builder.Bind<C1>().ToSelf().WithKey("foo").InPerContainerScope();
|
||||||
|
var parent = builder.BuildContainer();
|
||||||
|
|
||||||
|
var child = parent.CreateChildBuilder().BuildContainer();
|
||||||
|
|
||||||
|
var funcFromParent = parent.Get<Func<string, C1>>();
|
||||||
|
var funcFromChild = child.Get<Func<string, C1>>();
|
||||||
|
|
||||||
|
Assert.AreEqual(parent.Get<C1>("foo"), funcFromParent("foo"));
|
||||||
|
Assert.AreEqual(child.Get<C1>("foo"), funcFromChild("foo"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue