Skip to content

Commit

Permalink
Added new When overloads
Browse files Browse the repository at this point in the history
  • Loading branch information
remogloor committed Oct 7, 2011
1 parent fb4cc8c commit 60443ba
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 0 deletions.
3 changes: 3 additions & 0 deletions ReleaseNotes.txt
Expand Up @@ -2,6 +2,9 @@ Version 2.4.0.0
---------------
- Added: Support for default parameters. If not explicit binding exists for a dependency but there is default value defined it is uesd instead.
- Added: Support to define the constructor and constructor arguments using ToConstructor "to" overload
- Added: WhenInjectedExactlyInto When overload: Matches only if the target is exactly the specified type. This was the behavior of WhenInjectedInto in Ninject 2.2.
- Added: WhenAnyAnchestorNamed. Matches if any of the anchestor bindings is named with the specified name.
- Changed: WhenInjectedInto matches also if the target derives from the specified type.
- Changed: ToConstant bindings are in singleton scope by default
- Changed: Separate project for medium trust environments.
- Changed: Open generic bindings can be overwritten by closed generic bindings
Expand Down
48 changes: 48 additions & 0 deletions src/Ninject.Test/Integration/ConditionalBindingTests.cs
@@ -1,5 +1,6 @@
namespace Ninject.Tests.Integration
{
using System;
using System.Linq;
using FluentAssertions;
using Ninject.Tests.Fakes;
Expand Down Expand Up @@ -132,5 +133,52 @@ public void GivenOnlyImplicitBindings_AllBindingsWillResolve()
result.Should().Contain(shortSword);
result.Should().Contain(shuriken);
}

[Fact]
public void WhenInjectedIntoAppliesToBaseTypes()
{
kernel.Bind<IWarrior>().To<Samurai>();
kernel.Bind<IWeapon>().To<Sword>().WhenInjectedInto<IWarrior>();

var warrior = kernel.Get<IWarrior>();

warrior.Weapon.Should().BeOfType<Sword>();
}

[Fact]
public void WhenInjectedExactlyIntoAppliesNotToBaseTypes()
{
kernel.Bind<IWarrior>().To<Samurai>();
kernel.Bind<IWeapon>().To<Sword>().WhenInjectedExactlyInto<IWarrior>();

Action getWarrior = () => kernel.Get<IWarrior>();

getWarrior.ShouldThrow<ActivationException>();
}

[Fact]
public void WhenInjectedExactlyIntoAppliesToServiceType()
{
kernel.Bind<IWarrior>().To<Samurai>();
kernel.Bind<IWeapon>().To<Sword>().WhenInjectedExactlyInto<Samurai>();

var warrior = kernel.Get<IWarrior>();

warrior.Weapon.Should().BeOfType<Sword>();
}

[Fact]
public void WhenAnyAnchestorNamedAppliesToGrandParentAndParent()
{
const string Name = "SomeName";
kernel.Bind<Barracks>().ToSelf().Named(Name);
kernel.Bind<IWarrior>().To<Samurai>();
kernel.Bind<IWeapon>().To<Sword>().WhenAnyAnchestorNamed(Name);

var barack = kernel.Get<Barracks>();

barack.Weapon.Should().BeOfType<Sword>();
barack.Warrior.Weapon.Should().BeOfType<Sword>();
}
}
}
49 changes: 49 additions & 0 deletions src/Ninject/Planning/Bindings/BindingBuilder.cs
Expand Up @@ -186,6 +186,7 @@ public IBindingInNamedWithOrOnSyntax<T> When(Func<IRequest, bool> condition)

/// <summary>
/// Indicates that the binding should be used only for injections on the specified type.
/// Types that derive from the specified type are considered as valid targets.
/// </summary>
/// <typeparam name="TParent">The type.</typeparam>
public IBindingInNamedWithOrOnSyntax<T> WhenInjectedInto<TParent>()
Expand All @@ -195,9 +196,33 @@ public IBindingInNamedWithOrOnSyntax<T> WhenInjectedInto<TParent>()

/// <summary>
/// Indicates that the binding should be used only for injections on the specified type.
/// Types that derive from the specified type are considered as valid targets.
/// </summary>
/// <param name="parent">The type.</param>
public IBindingInNamedWithOrOnSyntax<T> WhenInjectedInto(Type parent)
{
Binding.Condition = r => r.Target != null && parent.IsAssignableFrom(r.Target.Member.ReflectedType);
return this;
}

/// <summary>
/// Indicates that the binding should be used only for injections on the specified type.
/// The type must match exactly the specified type. Types that derive from the specified type
/// will not be considered as valid target.
/// </summary>
/// <typeparam name="TParent">The type.</typeparam>
public IBindingInNamedWithOrOnSyntax<T> WhenInjectedExactlyInto<TParent>()
{
return WhenInjectedExactlyInto(typeof(TParent));
}

/// <summary>
/// Indicates that the binding should be used only for injections on the specified type.
/// The type must match exactly the specified type. Types that derive from the specified type
/// will not be considered as valid target.
/// </summary>
/// <param name="parent">The type.</param>
public IBindingInNamedWithOrOnSyntax<T> WhenInjectedExactlyInto(Type parent)
{
Binding.Condition = r => r.Target != null && r.Target.Member.ReflectedType == parent;
return this;
Expand Down Expand Up @@ -290,6 +315,30 @@ public IBindingInNamedWithOrOnSyntax<T> WhenParentNamed(string name)
return this;
}

/// <summary>
/// Indicates that the binding should be used only when the service is being requested
/// by a service bound with the specified name or any of its anchestor services bound with the specified name.
/// </summary>
/// <param name="name">The name to expect.</param>
public IBindingInNamedWithOrOnSyntax<T> WhenAnyAnchestorNamed(string name)
{
Binding.Condition = r => IsAnyAnchestorNamed(r, name);
return this;
}

private static bool IsAnyAnchestorNamed(IRequest request, string name)
{
var parentContext = request.ParentContext;
if (parentContext == null)
{
return false;
}

return
string.Equals(parentContext.Binding.Metadata.Name, name, StringComparison.Ordinal) ||
IsAnyAnchestorNamed(parentContext.Request, name);
}

/// <summary>
/// Indicates that the binding should be registered with the specified name. Names are not
/// necessarily unique; multiple bindings for a given service may be registered with the same name.
Expand Down
25 changes: 25 additions & 0 deletions src/Ninject/Syntax/BindingSyntax.cs
Expand Up @@ -103,16 +103,34 @@ public interface IBindingWhenSyntax<T> : IBindingSyntax

/// <summary>
/// Indicates that the binding should be used only for injections on the specified type.
/// Types that derive from the specified type are considered as valid targets.
/// </summary>
/// <typeparam name="TParent">The type.</typeparam>
IBindingInNamedWithOrOnSyntax<T> WhenInjectedInto<TParent>();

/// <summary>
/// Indicates that the binding should be used only for injections on the specified type.
/// Types that derive from the specified type are considered as valid targets.
/// </summary>
/// <param name="parent">The type.</param>
IBindingInNamedWithOrOnSyntax<T> WhenInjectedInto(Type parent);

/// <summary>
/// Indicates that the binding should be used only for injections on the specified type.
/// The type must match exactly the specified type. Types that derive from the specified type
/// will not be considered as valid target.
/// </summary>
/// <typeparam name="TParent">The type.</typeparam>
IBindingInNamedWithOrOnSyntax<T> WhenInjectedExactlyInto<TParent>();

/// <summary>
/// Indicates that the binding should be used only for injections on the specified type.
/// The type must match exactly the specified type. Types that derive from the specified type
/// will not be considered as valid target.
/// </summary>
/// <param name="parent">The type.</param>
IBindingInNamedWithOrOnSyntax<T> WhenInjectedExactlyInto(Type parent);

/// <summary>
/// Indicates that the binding should be used only when the class being injected has
/// an attribute of the specified type.
Expand Down Expand Up @@ -161,6 +179,13 @@ public interface IBindingWhenSyntax<T> : IBindingSyntax
/// </summary>
/// <param name="name">The name to expect.</param>
IBindingInNamedWithOrOnSyntax<T> WhenParentNamed(string name);

/// <summary>
/// Indicates that the binding should be used only when the service is being requested
/// by a service bound with the specified name or any of its anchestor services bound with the specified name.
/// </summary>
/// <param name="name">The name to expect.</param>
IBindingInNamedWithOrOnSyntax<T> WhenAnyAnchestorNamed(string name);
}

/// <summary>
Expand Down

0 comments on commit 60443ba

Please sign in to comment.