From 132ce47d14237532c590c90a2aab90a8ebc02118 Mon Sep 17 00:00:00 2001 From: Jarrett Meyer Date: Thu, 10 May 2012 14:58:40 -0400 Subject: [PATCH 1/6] added support for default scope callback setting --- .../Integration/DefaultScopeCallbackTests.cs | 31 +++++++++++++++++++ src/Ninject.Test/Ninject.Tests.csproj | 1 + src/Ninject/INinjectSettings.cs | 7 +++++ src/Ninject/KernelBase.cs | 2 +- src/Ninject/NinjectSettings.cs | 12 +++++++ src/Ninject/Planning/Bindings/Binding.cs | 5 +-- .../Planning/Bindings/BindingConfiguration.cs | 8 ++++- .../Resolvers/DefaultValueBindingResolver.cs | 2 +- .../Bindings/Resolvers/SelfBindingResolver.cs | 2 +- src/Ninject/Syntax/BindingRoot.cs | 12 +++---- 10 files changed, 70 insertions(+), 12 deletions(-) create mode 100644 src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs diff --git a/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs b/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs new file mode 100644 index 00000000..54b86b57 --- /dev/null +++ b/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs @@ -0,0 +1,31 @@ +namespace Ninject.Tests.Integration.DefaultScopeCallbackTests +{ + using System; + using FluentAssertions; + using Ninject.Infrastructure; + using Xunit; + + public class DefaultScopeContext : IDisposable + { + protected StandardKernel kernel; + + public DefaultScopeContext() + { + this.kernel = new StandardKernel(); + } + + public void Dispose() + { + this.kernel.Dispose(); + } + } + + public class WhenKernelIsCreatedWithDefaults : DefaultScopeContext + { + [Fact] + public void ScopeShouldBeTransient() + { + kernel.Settings.DefaultScopeCallback.Should().BeSameAs(StandardScopeCallbacks.Transient); + } + } +} diff --git a/src/Ninject.Test/Ninject.Tests.csproj b/src/Ninject.Test/Ninject.Tests.csproj index e719017a..ed4c6807 100644 --- a/src/Ninject.Test/Ninject.Tests.csproj +++ b/src/Ninject.Test/Ninject.Tests.csproj @@ -94,6 +94,7 @@ + diff --git a/src/Ninject/INinjectSettings.cs b/src/Ninject/INinjectSettings.cs index 5104ca36..014d9474 100644 --- a/src/Ninject/INinjectSettings.cs +++ b/src/Ninject/INinjectSettings.cs @@ -9,6 +9,8 @@ #endregion #region Using Directives using System; +using Ninject.Activation; + #endregion namespace Ninject @@ -28,6 +30,11 @@ public interface INinjectSettings /// TimeSpan CachePruningInterval { get; } + /// + /// Gets the default scope callback. + /// + Func DefaultScopeCallback { get; } + #if !NO_ASSEMBLY_SCANNING /// /// Gets a value indicating whether the kernel should automatically load extensions at startup. diff --git a/src/Ninject/KernelBase.cs b/src/Ninject/KernelBase.cs index 0a1843a7..aadc53dd 100644 --- a/src/Ninject/KernelBase.cs +++ b/src/Ninject/KernelBase.cs @@ -281,7 +281,7 @@ public virtual void Inject(object instance, params IParameter[] parameters) var planner = this.Components.Get(); var pipeline = this.Components.Get(); - var binding = new Binding(service); + var binding = new Binding(service, Settings.DefaultScopeCallback); var request = this.CreateRequest(service, null, parameters, false, false); var context = this.CreateContext(request, binding); diff --git a/src/Ninject/NinjectSettings.cs b/src/Ninject/NinjectSettings.cs index a3b9e8c0..6071daed 100644 --- a/src/Ninject/NinjectSettings.cs +++ b/src/Ninject/NinjectSettings.cs @@ -10,6 +10,9 @@ #region Using Directives using System; using System.Collections.Generic; +using Ninject.Activation; +using Ninject.Infrastructure; + #endregion namespace Ninject @@ -39,6 +42,15 @@ public TimeSpan CachePruningInterval set { Set("CachePruningInterval", value); } } + /// + /// Gets or sets the default scope callback. + /// + public Func DefaultScopeCallback + { + get { return Get("DefaultScopeCallback", StandardScopeCallbacks.Transient); } + set { Set("DefaultScopeCallback", value); } + } + #if !NO_ASSEMBLY_SCANNING /// /// Gets or sets a value indicating whether the kernel should automatically load extensions at startup. diff --git a/src/Ninject/Planning/Bindings/Binding.cs b/src/Ninject/Planning/Bindings/Binding.cs index 6d645feb..e25d0cac 100644 --- a/src/Ninject/Planning/Bindings/Binding.cs +++ b/src/Ninject/Planning/Bindings/Binding.cs @@ -26,12 +26,13 @@ public class Binding : IBinding /// Initializes a new instance of the class. /// /// The service that is controlled by the binding. - public Binding(Type service) + /// + public Binding(Type service, Func defaultScopeCallback) { Ensure.ArgumentNotNull(service, "service"); this.Service = service; - this.BindingConfiguration = new BindingConfiguration(); + this.BindingConfiguration = new BindingConfiguration(defaultScopeCallback); } /// diff --git a/src/Ninject/Planning/Bindings/BindingConfiguration.cs b/src/Ninject/Planning/Bindings/BindingConfiguration.cs index 05407779..968718ec 100644 --- a/src/Ninject/Planning/Bindings/BindingConfiguration.cs +++ b/src/Ninject/Planning/Bindings/BindingConfiguration.cs @@ -36,12 +36,18 @@ public class BindingConfiguration : IBindingConfiguration /// Initializes a new instance of the class. /// public BindingConfiguration() + : this(StandardScopeCallbacks.Transient) { } + + /// + /// Initializes a new instance of the class. + /// + public BindingConfiguration(Func scopeCallback) { this.Metadata = new BindingMetadata(); this.Parameters = new List(); this.ActivationActions = new List>(); this.DeactivationActions = new List>(); - this.ScopeCallback = StandardScopeCallbacks.Transient; + this.ScopeCallback = scopeCallback ?? StandardScopeCallbacks.Transient; } /// diff --git a/src/Ninject/Planning/Bindings/Resolvers/DefaultValueBindingResolver.cs b/src/Ninject/Planning/Bindings/Resolvers/DefaultValueBindingResolver.cs index ea37ed19..3e9abe69 100644 --- a/src/Ninject/Planning/Bindings/Resolvers/DefaultValueBindingResolver.cs +++ b/src/Ninject/Planning/Bindings/Resolvers/DefaultValueBindingResolver.cs @@ -38,7 +38,7 @@ public IEnumerable Resolve(Multimap bindings, IRequest return HasDefaultValue(request.Target) ? new[] { - new Binding(service) + new Binding(service, Settings.DefaultScopeCallback) { Condition = r => HasDefaultValue(r.Target), ProviderCallback = _ => new DefaultParameterValueProvider(service), diff --git a/src/Ninject/Planning/Bindings/Resolvers/SelfBindingResolver.cs b/src/Ninject/Planning/Bindings/Resolvers/SelfBindingResolver.cs index 5517f341..a27bc24d 100644 --- a/src/Ninject/Planning/Bindings/Resolvers/SelfBindingResolver.cs +++ b/src/Ninject/Planning/Bindings/Resolvers/SelfBindingResolver.cs @@ -40,7 +40,7 @@ public IEnumerable Resolve(Multimap bindings, IRequest } return new[] { - new Binding(service) + new Binding(service, Settings.DefaultScopeCallback) { ProviderCallback = StandardProvider.GetCreationCallback(service) } diff --git a/src/Ninject/Syntax/BindingRoot.cs b/src/Ninject/Syntax/BindingRoot.cs index 10d113f2..8f26e78e 100644 --- a/src/Ninject/Syntax/BindingRoot.cs +++ b/src/Ninject/Syntax/BindingRoot.cs @@ -51,7 +51,7 @@ public IBindingToSyntax Bind() { Type service = typeof(T); - var binding = new Binding(service); + var binding = new Binding(service, KernelInstance.Settings.DefaultScopeCallback); this.AddBinding(binding); return new BindingBuilder(binding, this.KernelInstance, service.Format()); @@ -65,7 +65,7 @@ public IBindingToSyntax Bind() /// The fluent syntax public IBindingToSyntax Bind() { - var firstBinding = new Binding(typeof(T1)); + var firstBinding = new Binding(typeof(T1), KernelInstance.Settings.DefaultScopeCallback); this.AddBinding(firstBinding); this.AddBinding(new Binding(typeof(T2), firstBinding.BindingConfiguration)); var servceNames = new[] { typeof(T1).Format(), typeof(T2).Format() }; @@ -82,7 +82,7 @@ public IBindingToSyntax Bind() /// The fluent syntax public IBindingToSyntax Bind() { - var firstBinding = new Binding(typeof(T1)); + var firstBinding = new Binding(typeof(T1), KernelInstance.Settings.DefaultScopeCallback); this.AddBinding(firstBinding); this.AddBinding(new Binding(typeof(T2), firstBinding.BindingConfiguration)); this.AddBinding(new Binding(typeof(T3), firstBinding.BindingConfiguration)); @@ -101,7 +101,7 @@ public IBindingToSyntax Bind() /// The fluent syntax public IBindingToSyntax Bind() { - var firstBinding = new Binding(typeof(T1)); + var firstBinding = new Binding(typeof(T1), KernelInstance.Settings.DefaultScopeCallback); this.AddBinding(firstBinding); this.AddBinding(new Binding(typeof(T2), firstBinding.BindingConfiguration)); this.AddBinding(new Binding(typeof(T3), firstBinding.BindingConfiguration)); @@ -122,9 +122,9 @@ public IBindingToSyntax Bind(params Type[] services) if (services.Length == 0) { throw new ArgumentException("The services must contain at least one type", "services"); - } + } - var firstBinding = new Binding(services[0]); + var firstBinding = new Binding(services[0], KernelInstance.Settings.DefaultScopeCallback); this.AddBinding(firstBinding); foreach (var service in services.Skip(1)) From 955faaf975bde1b2ad3bbc260608b2dc405a2136 Mon Sep 17 00:00:00 2001 From: Jarrett Meyer Date: Mon, 21 May 2012 17:25:40 -0400 Subject: [PATCH 2/6] added tests to default scope callback --- .../Integration/DefaultScopeCallbackTests.cs | 91 ++++++++++++++++++- src/Ninject/Activation/Request.cs | 2 +- 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs b/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs index 54b86b57..1b529962 100644 --- a/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs +++ b/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs @@ -1,6 +1,12 @@ -namespace Ninject.Tests.Integration.DefaultScopeCallbackTests +using System.Collections.Generic; +using Ninject.Activation; +using Ninject.Parameters; +using Ninject.Planning.Bindings; + +namespace Ninject.Tests.Integration.DefaultScopeCallbackTests { using System; + using System.Linq; using FluentAssertions; using Ninject.Infrastructure; using Xunit; @@ -11,21 +17,102 @@ public class DefaultScopeContext : IDisposable public DefaultScopeContext() { - this.kernel = new StandardKernel(); + InitializeKernel(); } public void Dispose() { this.kernel.Dispose(); } + + protected virtual void InitializeKernel() + { + this.kernel = new StandardKernel(); + } + + public interface IService { } + + public class ServiceImpl : IService { } } public class WhenKernelIsCreatedWithDefaults : DefaultScopeContext { + [Fact] + public void CanOverrideDefaultScopeWithSingletonInBinding() + { + kernel.Bind().To().InSingletonScope(); + var binding = kernel.GetBindings(typeof(IService)).FirstOrDefault(); + binding.ScopeCallback.Should().BeSameAs(StandardScopeCallbacks.Singleton); + } + + [Fact] + public void CanOverrideDefaultScopeWithThreadInBinding() + { + kernel.Bind().To().InThreadScope(); + var binding = kernel.GetBindings(typeof(IService)).FirstOrDefault(); + binding.ScopeCallback.Should().BeSameAs(StandardScopeCallbacks.Thread); + } + [Fact] public void ScopeShouldBeTransient() { kernel.Settings.DefaultScopeCallback.Should().BeSameAs(StandardScopeCallbacks.Transient); } } + + public class WhenKernelIsCreatedWithNewObjectScope : DefaultScopeContext + { + private Func scopeDelegate; + + [Fact] + public void ScopeShouldBeObject() + { + this.kernel.Settings.DefaultScopeCallback.Should().BeSameAs(scopeDelegate); + } + + protected override void InitializeKernel() + { + object obj = new object(); + scopeDelegate = ctx => obj; + var settings = new NinjectSettings + { + DefaultScopeCallback = scopeDelegate + }; + this.kernel = new StandardKernel(settings); + } + } + + public class WhenKernelIsCreatedWithTheadScopeAsDefault : DefaultScopeContext + { + [Fact] + public void CanOverrideDefaultScopeWithSingletonInBinding() + { + kernel.Bind().To().InSingletonScope(); + var binding = kernel.GetBindings(typeof(IService)).FirstOrDefault(); + binding.ScopeCallback.Should().BeSameAs(StandardScopeCallbacks.Singleton); + } + + [Fact] + public void CanOverrideDefaultScopeWithTransientInBinding() + { + kernel.Bind().To().InTransientScope(); + var binding = kernel.GetBindings(typeof(IService)).FirstOrDefault(); + binding.ScopeCallback.Should().BeSameAs(StandardScopeCallbacks.Transient); + } + + [Fact] + public void ScopeShouldBeThread() + { + kernel.Settings.DefaultScopeCallback.Should().BeSameAs(StandardScopeCallbacks.Thread); + } + + protected override void InitializeKernel() + { + var settings = new NinjectSettings + { + DefaultScopeCallback = StandardScopeCallbacks.Thread + }; + this.kernel = new StandardKernel(settings); + } + } } diff --git a/src/Ninject/Activation/Request.cs b/src/Ninject/Activation/Request.cs index 54185cea..2c0796dc 100644 --- a/src/Ninject/Activation/Request.cs +++ b/src/Ninject/Activation/Request.cs @@ -113,7 +113,7 @@ public Request(Type service, Func constraint, IEnumerabl /// The service that was requested. /// The target that will receive the injection. /// The scope callback, if an external scope was specified. - public Request(IContext parentContext, Type service, ITarget target, Func scopeCallback) + private Request(IContext parentContext, Type service, ITarget target, Func scopeCallback) { Ensure.ArgumentNotNull(parentContext, "parentContext"); Ensure.ArgumentNotNull(service, "service"); From d1a22be7e3ce3c46deed7e2d5d4f3c4a23200a11 Mon Sep 17 00:00:00 2001 From: Jarrett Meyer Date: Tue, 22 May 2012 09:39:45 -0400 Subject: [PATCH 3/6] Fixed name. Added test for self binded types. Test fails --- .../Integration/DefaultScopeCallbackTests.cs | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs b/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs index 1b529962..631dbc1d 100644 --- a/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs +++ b/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs @@ -30,9 +30,24 @@ protected virtual void InitializeKernel() this.kernel = new StandardKernel(); } + protected virtual void TestSelfBindedTypesAreTransient() + { + var firstInstance = kernel.Get(); + var secondInstance = kernel.Get(); + firstInstance.Should().NotBeSameAs(secondInstance, "because types are transient"); + } + public interface IService { } public class ServiceImpl : IService { } + + public class SelfBindedType + { + public override string ToString() + { + return "SelfBindedType"; + } + } } public class WhenKernelIsCreatedWithDefaults : DefaultScopeContext @@ -58,6 +73,12 @@ public void ScopeShouldBeTransient() { kernel.Settings.DefaultScopeCallback.Should().BeSameAs(StandardScopeCallbacks.Transient); } + + [Fact] + public void SelfBindedTypeShouldBeTransient() + { + TestSelfBindedTypesAreTransient(); + } } public class WhenKernelIsCreatedWithNewObjectScope : DefaultScopeContext @@ -70,6 +91,12 @@ public void ScopeShouldBeObject() this.kernel.Settings.DefaultScopeCallback.Should().BeSameAs(scopeDelegate); } + [Fact] + public void SelfBindedTypeShouldBeTransient() + { + TestSelfBindedTypesAreTransient(); + } + protected override void InitializeKernel() { object obj = new object(); @@ -82,7 +109,7 @@ protected override void InitializeKernel() } } - public class WhenKernelIsCreatedWithTheadScopeAsDefault : DefaultScopeContext + public class WhenKernelIsCreatedWithThreadScopeAsDefault : DefaultScopeContext { [Fact] public void CanOverrideDefaultScopeWithSingletonInBinding() @@ -106,6 +133,12 @@ public void ScopeShouldBeThread() kernel.Settings.DefaultScopeCallback.Should().BeSameAs(StandardScopeCallbacks.Thread); } + [Fact] + public void SelfBindedTypeShouldBeTransient() + { + TestSelfBindedTypesAreTransient(); + } + protected override void InitializeKernel() { var settings = new NinjectSettings From e965297437395bc68ca3adabafef8e63b051f4fb Mon Sep 17 00:00:00 2001 From: Jarrett Meyer Date: Tue, 22 May 2012 09:41:34 -0400 Subject: [PATCH 4/6] Fixed ctor in Request --- src/Ninject/Activation/Request.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ninject/Activation/Request.cs b/src/Ninject/Activation/Request.cs index 2c0796dc..54185cea 100644 --- a/src/Ninject/Activation/Request.cs +++ b/src/Ninject/Activation/Request.cs @@ -113,7 +113,7 @@ public Request(Type service, Func constraint, IEnumerabl /// The service that was requested. /// The target that will receive the injection. /// The scope callback, if an external scope was specified. - private Request(IContext parentContext, Type service, ITarget target, Func scopeCallback) + public Request(IContext parentContext, Type service, ITarget target, Func scopeCallback) { Ensure.ArgumentNotNull(parentContext, "parentContext"); Ensure.ArgumentNotNull(service, "service"); From fb3f9228fc497a53dea815348a1cffbd8fd7ee70 Mon Sep 17 00:00:00 2001 From: Jarrett Meyer Date: Tue, 22 May 2012 10:05:43 -0400 Subject: [PATCH 5/6] Adds constructor back to Binding class. Default functionality in Ninject was always transient. This change should maintain this behavior except when explicit bindings are configured. --- src/Ninject/KernelBase.cs | 2 +- src/Ninject/Planning/Bindings/Binding.cs | 15 ++++++++++++--- .../Resolvers/DefaultValueBindingResolver.cs | 2 +- .../Bindings/Resolvers/SelfBindingResolver.cs | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/Ninject/KernelBase.cs b/src/Ninject/KernelBase.cs index aadc53dd..0a1843a7 100644 --- a/src/Ninject/KernelBase.cs +++ b/src/Ninject/KernelBase.cs @@ -281,7 +281,7 @@ public virtual void Inject(object instance, params IParameter[] parameters) var planner = this.Components.Get(); var pipeline = this.Components.Get(); - var binding = new Binding(service, Settings.DefaultScopeCallback); + var binding = new Binding(service); var request = this.CreateRequest(service, null, parameters, false, false); var context = this.CreateContext(request, binding); diff --git a/src/Ninject/Planning/Bindings/Binding.cs b/src/Ninject/Planning/Bindings/Binding.cs index e25d0cac..ea0f4974 100644 --- a/src/Ninject/Planning/Bindings/Binding.cs +++ b/src/Ninject/Planning/Bindings/Binding.cs @@ -26,13 +26,22 @@ public class Binding : IBinding /// Initializes a new instance of the class. /// /// The service that is controlled by the binding. - /// - public Binding(Type service, Func defaultScopeCallback) + public Binding(Type service) + : this(service, StandardScopeCallbacks.Transient) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The service that is controlled by the binding. + /// The scope callback for the service. + public Binding(Type service, Func scopeCallback) { Ensure.ArgumentNotNull(service, "service"); this.Service = service; - this.BindingConfiguration = new BindingConfiguration(defaultScopeCallback); + this.BindingConfiguration = new BindingConfiguration(scopeCallback); } /// diff --git a/src/Ninject/Planning/Bindings/Resolvers/DefaultValueBindingResolver.cs b/src/Ninject/Planning/Bindings/Resolvers/DefaultValueBindingResolver.cs index 3e9abe69..ea37ed19 100644 --- a/src/Ninject/Planning/Bindings/Resolvers/DefaultValueBindingResolver.cs +++ b/src/Ninject/Planning/Bindings/Resolvers/DefaultValueBindingResolver.cs @@ -38,7 +38,7 @@ public IEnumerable Resolve(Multimap bindings, IRequest return HasDefaultValue(request.Target) ? new[] { - new Binding(service, Settings.DefaultScopeCallback) + new Binding(service) { Condition = r => HasDefaultValue(r.Target), ProviderCallback = _ => new DefaultParameterValueProvider(service), diff --git a/src/Ninject/Planning/Bindings/Resolvers/SelfBindingResolver.cs b/src/Ninject/Planning/Bindings/Resolvers/SelfBindingResolver.cs index a27bc24d..5517f341 100644 --- a/src/Ninject/Planning/Bindings/Resolvers/SelfBindingResolver.cs +++ b/src/Ninject/Planning/Bindings/Resolvers/SelfBindingResolver.cs @@ -40,7 +40,7 @@ public IEnumerable Resolve(Multimap bindings, IRequest } return new[] { - new Binding(service, Settings.DefaultScopeCallback) + new Binding(service) { ProviderCallback = StandardProvider.GetCreationCallback(service) } From c730223913b242b2504ed562a2b5f78e4de08945 Mon Sep 17 00:00:00 2001 From: Jarrett Meyer Date: Tue, 22 May 2012 10:41:46 -0400 Subject: [PATCH 6/6] Added unit tests for implicit vs. explicit self binded types. All unit tests pass. Implicit self binded types are always transient, again keeping with the way Ninject should behave. Validates that explicitly bound types will use the default scope. --- .../Integration/DefaultScopeCallbackTests.cs | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs b/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs index 631dbc1d..9e85f156 100644 --- a/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs +++ b/src/Ninject.Test/Integration/DefaultScopeCallbackTests.cs @@ -75,10 +75,18 @@ public void ScopeShouldBeTransient() } [Fact] - public void SelfBindedTypeShouldBeTransient() + public void ImplicitSelfBindedTypeShouldBeTransient() { TestSelfBindedTypesAreTransient(); } + + [Fact] + public void ExplicitSelfBindedTypeShouldBeTransient() + { + kernel.Bind().ToSelf(); + var binding = kernel.GetBindings(typeof(SelfBindedType)).FirstOrDefault(); + binding.ScopeCallback.Should().BeSameAs(StandardScopeCallbacks.Transient); + } } public class WhenKernelIsCreatedWithNewObjectScope : DefaultScopeContext @@ -92,11 +100,19 @@ public void ScopeShouldBeObject() } [Fact] - public void SelfBindedTypeShouldBeTransient() + public void ImplicitSelfBindedTypeShouldBeTransient() { TestSelfBindedTypesAreTransient(); } + [Fact] + public void ExplicitSelfBindedTypeShouldHaveObjectScope() + { + kernel.Bind().ToSelf(); + var binding = kernel.GetBindings(typeof(SelfBindedType)).FirstOrDefault(); + binding.ScopeCallback.Should().BeSameAs(scopeDelegate); + } + protected override void InitializeKernel() { object obj = new object(); @@ -134,11 +150,19 @@ public void ScopeShouldBeThread() } [Fact] - public void SelfBindedTypeShouldBeTransient() + public void ImplicitSelfBindedTypeShouldBeTransient() { TestSelfBindedTypesAreTransient(); } + [Fact] + public void ExplicitSelfBindedTypeShouldHaveThreadScope() + { + kernel.Bind().ToSelf(); + var binding = kernel.GetBindings(typeof(SelfBindedType)).FirstOrDefault(); + binding.ScopeCallback.Should().BeSameAs(StandardScopeCallbacks.Thread); + } + protected override void InitializeKernel() { var settings = new NinjectSettings