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 namespace StyletIoC.Creation
{ {
/// <summary>
/// Defines and type + key for a service, used in setting up bindings
/// </summary>
public class BuilderTypeKey : IEquatable<BuilderTypeKey> public class BuilderTypeKey : IEquatable<BuilderTypeKey>
{ {
/// <summary>
/// Gets or sets the Type associated with this Type+Key
/// </summary>
public Type Type { get; set; } public Type Type { get; set; }
/// <summary>
/// Gets or sets the Key associated with this Type+Key
/// </summary>
public string Key { get; set; } 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) public BuilderTypeKey(Type type)
{ {
this.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) public BuilderTypeKey(Type type, string key)
{ {
this.Type = type; this.Type = type;
this.Key = key; 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) public override bool Equals(object obj)
{ {
return base.Equals(obj as BuilderTypeKey); 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() public override int GetHashCode()
{ {
unchecked 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) public bool Equals(BuilderTypeKey other)
{ {
return other != null && 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 public interface IToMultipleServices
{ {
/// <summary> /// <summary>
@ -45,6 +48,9 @@ namespace StyletIoC
IWithKeyOrAsWeakBinding ToInstance(object instance); IWithKeyOrAsWeakBinding ToInstance(object instance);
} }
/// <summary>
/// Interface providing binding options for a single service, or multiple services
/// </summary>
public interface IToAnyService : IToMultipleServices public interface IToAnyService : IToMultipleServices
{ {
/// <summary> /// <summary>
@ -74,21 +80,49 @@ namespace StyletIoC
IInScopeOrWithKeyOrAsWeakBinding ToAllImplementations(params Assembly[] assemblies); IInScopeOrWithKeyOrAsWeakBinding ToAllImplementations(params Assembly[] assemblies);
} }
/// <summary>
/// Interface providing 'And' binding options
/// </summary>
public interface IAndTo 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); 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>(); IWithKeyOrAndOrToMultipleServices And<TService>();
} }
/// <summary>
/// Interface providing options 'WithKey' or 'ToXXX' for multiple services
/// </summary>
public interface IWithKeyOrToMulipleServices : IToMultipleServices 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); IAndOrToMultipleServices WithKey(string key);
} }
/// <summary>
/// Interface providing 'And' or 'ToXXX' for multiple services
/// </summary>
public interface IAndOrToMultipleServices : IToMultipleServices, IAndTo public interface IAndOrToMultipleServices : IToMultipleServices, IAndTo
{ {
} }
/// <summary>
/// Interface providing 'WithKey' or 'And' or 'ToXXX' for multiple services
/// </summary>
public interface IWithKeyOrAndOrToMultipleServices : IWithKeyOrToMulipleServices, IAndTo public interface IWithKeyOrAndOrToMultipleServices : IWithKeyOrToMulipleServices, IAndTo
{ {
} }

View File

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

View File

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