Slightly more testing, and docs

This commit is contained in:
Antony Male 2015-10-03 16:55:53 +01:00
parent bd18b94e82
commit df7e024bf5
4 changed files with 97 additions and 16 deletions

View File

@ -2,27 +2,55 @@
namespace StyletIoC.Creation
{
/// <summary>
/// Defines and type + key for a service, used in setting up bindings
/// </summary>
public class BuilderTypeKey : IEquatable<BuilderTypeKey>
{
/// <summary>
/// Gets or sets the Type associated with this Type+Key
/// </summary>
public Type Type { get; set; }
/// <summary>
/// Gets or sets the Key associated with this Type+Key
/// </summary>
public string Key { get; set; }
/// <summary>
/// Initialises a new instance of the <see cref="BuilderTypeKey"/> class with the given type
/// </summary>
/// <param name="type">Type to associated with this Type+Key</param>
public BuilderTypeKey(Type type)
{
this.Type = type;
}
/// <summary>
/// Initialises a new instance of the <see cref="BuilderTypeKey"/> class with the given type and key
/// </summary>
/// <param name="type">Type to associated with this Type+Key</param>
/// <param name="key">Key to associated with this Type+Key</param>
public BuilderTypeKey(Type type, string key)
{
this.Type = type;
this.Key = key;
}
/// <summary>
/// Determines whether the specified object is equal to the current object.
/// </summary>
/// <param name="obj">The object to compare with the current object.</param>
/// <returns>true if the specified object is equal to the current object; otherwise, false</returns>
public override bool Equals(object obj)
{
return base.Equals(obj as BuilderTypeKey);
}
/// <summary>
/// Calculates a HashCode for the current object
/// </summary>
/// <returns>A hash code for the current object.</returns>
public override int GetHashCode()
{
unchecked
@ -35,6 +63,11 @@ namespace StyletIoC.Creation
}
}
/// <summary>
/// Determines whether the specified object is equal to the current object.
/// </summary>
/// <param name="other">The object to compare with the current object.</param>
/// <returns>true if the specified object is equal to the current object; otherwise, false</returns>
public bool Equals(BuilderTypeKey other)
{
return other != null &&

View File

@ -13,6 +13,9 @@ namespace StyletIoC
{
}
/// <summary>
/// Interface providing further options once a binding has been created which binds to multiple services
/// </summary>
public interface IToMultipleServices
{
/// <summary>
@ -45,6 +48,9 @@ namespace StyletIoC
IWithKeyOrAsWeakBinding ToInstance(object instance);
}
/// <summary>
/// Interface providing binding options for a single service, or multiple services
/// </summary>
public interface IToAnyService : IToMultipleServices
{
/// <summary>
@ -74,21 +80,49 @@ namespace StyletIoC
IInScopeOrWithKeyOrAsWeakBinding ToAllImplementations(params Assembly[] assemblies);
}
/// <summary>
/// Interface providing 'And' binding options
/// </summary>
public interface IAndTo
{
/// <summary>
/// Add another service to this binding
/// </summary>
/// <param name="serviceType">Service type to add to this binding</param>
/// <returns>Fluent interface to continue configuration</returns>
IWithKeyOrAndOrToMultipleServices And(Type serviceType);
/// <summary>
/// Add another service to this binding
/// </summary>
/// <typeparam name="TService">Service type to add to this binding</typeparam>
/// <returns>Fluent interface to continue configuration</returns>
IWithKeyOrAndOrToMultipleServices And<TService>();
}
/// <summary>
/// Interface providing options 'WithKey' or 'ToXXX' for multiple services
/// </summary>
public interface IWithKeyOrToMulipleServices : IToMultipleServices
{
/// <summary>
/// Add a key to this part of the multiple-service binding
/// </summary>
/// <param name="key">Key to add to this part of the multiple-service binding</param>
/// <returns>Fluent interface to continue configuration</returns>
IAndOrToMultipleServices WithKey(string key);
}
/// <summary>
/// Interface providing 'And' or 'ToXXX' for multiple services
/// </summary>
public interface IAndOrToMultipleServices : IToMultipleServices, IAndTo
{
}
/// <summary>
/// Interface providing 'WithKey' or 'And' or 'ToXXX' for multiple services
/// </summary>
public interface IWithKeyOrAndOrToMultipleServices : IWithKeyOrToMulipleServices, IAndTo
{
}

View File

@ -174,8 +174,8 @@ namespace StyletIoC
.ToLookup(x => x.ServiceType);
var filtered = from binding in this.bindings
where !binding.IsWeak ||
binding.ServiceTypes.Any(serviceType => groups.Contains(serviceType) && groups[serviceType].Any(groupItem => groupItem.Binding.IsWeak))
where !(binding.IsWeak &&
binding.ServiceTypes.Any(serviceType => groups.Contains(serviceType) && groups[serviceType].Any(groupItem => !groupItem.Binding.IsWeak)))
select binding;
foreach (var binding in filtered)

View File

@ -12,9 +12,10 @@ namespace StyletUnitTests
public class StyletIoCMultipleBindingTests
{
private interface I1 { }
private interface I11 { }
private interface I12 { }
private class C1 : I1 { }
private class C1 : I11, I12 { }
private interface I2<T> { }
private class C2<T> : I2<T> { }
@ -23,30 +24,30 @@ namespace StyletUnitTests
public void SingletonMultipleTypeBindingIsSingleton()
{
var builder = new StyletIoCBuilder();
builder.Bind<I1>().And<C1>().To<C1>().InSingletonScope();
builder.Bind<I11>().And<C1>().To<C1>().InSingletonScope();
var ioc = builder.BuildContainer();
Assert.AreEqual(ioc.Get<C1>(), ioc.Get<I1>());
Assert.AreEqual(ioc.Get<C1>(), ioc.Get<I11>());
}
[Test]
public void SingletonMultipleFactoryBindingIsSingleton()
{
var builder = new StyletIoCBuilder();
builder.Bind<I1>().And<C1>().ToFactory(x => new C1()).InSingletonScope();
builder.Bind<I11>().And<C1>().ToFactory(x => new C1()).InSingletonScope();
var ioc = builder.BuildContainer();
Assert.AreEqual(ioc.Get<C1>(), ioc.Get<I1>());
Assert.AreEqual(ioc.Get<C1>(), ioc.Get<I11>());
}
[Test]
public void SingletonMultipleInstanceBindingWorks()
{
var builder = new StyletIoCBuilder();
builder.Bind<I1>().And<C1>().ToInstance(new C1());
builder.Bind<I11>().And<C1>().ToInstance(new C1());
var ioc = builder.BuildContainer();
Assert.AreEqual(ioc.Get<C1>(), ioc.Get<I1>());
Assert.AreEqual(ioc.Get<C1>(), ioc.Get<I11>());
}
[Test]
@ -61,7 +62,7 @@ namespace StyletUnitTests
public void RejectsMultipleBindingsForTheSameType()
{
var builder = new StyletIoCBuilder();
builder.Bind<I1>().And<I1>().To<C1>();
builder.Bind<I11>().And<I11>().To<C1>();
Assert.Throws<StyletIoCRegistrationException>(() => builder.BuildContainer());
}
@ -69,22 +70,35 @@ namespace StyletUnitTests
public void AllowsMultipleBindingsWithDifferentKeys()
{
var builder = new StyletIoCBuilder();
builder.Bind<I1>().WithKey("foo").And<I1>().To<C1>().InSingletonScope();
builder.Bind<I11>().WithKey("foo").And<I11>().To<C1>().InSingletonScope();
var ioc = builder.BuildContainer();
Assert.AreEqual(ioc.Get<I1>(), ioc.Get<I1>("foo"));
Assert.AreEqual(ioc.Get<I11>(), ioc.Get<I11>("foo"));
}
[Test]
public void FinalWithKeyAppliesToAllBindings()
{
var builder = new StyletIoCBuilder();
builder.Bind<I1>().And<C1>().To<C1>().WithKey("foo").InSingletonScope();
builder.Bind<I11>().And<C1>().To<C1>().WithKey("foo").InSingletonScope();
var ioc = builder.BuildContainer();
Assert.DoesNotThrow(() => ioc.Get<I1>("foo"));
Assert.DoesNotThrow(() => ioc.Get<I11>("foo"));
Assert.DoesNotThrow(() => ioc.Get<C1>("foo"));
Assert.AreEqual(ioc.Get<I1>("foo"), ioc.Get<C1>("foo"));
Assert.AreEqual(ioc.Get<I11>("foo"), ioc.Get<C1>("foo"));
}
[Test]
public void WeakBindingsRemoveIfAnyOtherStrongBindingWithSameTypeAndKeyExists()
{
var builder = new StyletIoCBuilder();
builder.Bind<I11>().And<C1>().To<C1>().AsWeakBinding();
builder.Bind<I12>().And<C1>().To<C1>();
var ioc = builder.BuildContainer();
Assert.AreEqual(0, ioc.GetAll<I11>().Count());
Assert.AreEqual(1, ioc.GetAll<C1>().Count());
Assert.AreEqual(1, ioc.GetAll<I12>().Count());
}
}
}