Created
March 9, 2010 07:00
-
-
Save danielmarbach/326321 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Implements a heuristic for ninject property injection. | |
/// </summary> | |
public interface IObjectBuilderPropertyHeuristic : IInjectionHeuristic | |
{ | |
/// <summary> | |
/// Gets the registered types. | |
/// </summary> | |
/// <value>The registered types.</value> | |
IList<Type> RegisteredTypes | |
{ | |
get; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Only injects properties on an instance if that instance has not | |
/// been previously activated. This forces property injection to occur | |
/// only once for instances within a scope -- e.g. singleton or within | |
/// the same request, etc. Instances are removed on deactivation. | |
/// </summary> | |
public class NewActivationPropertyInjectStrategy : PropertyInjectionStrategy | |
{ | |
private readonly HashSet<object> activatedInstances = new HashSet<object>(); | |
/// <summary> | |
/// Initializes a new instance of the <see cref="NewActivationPropertyInjectStrategy"/> class. | |
/// </summary> | |
/// <param name="injectorFactory">The injector factory component.</param> | |
public NewActivationPropertyInjectStrategy(IInjectorFactory injectorFactory) | |
: base(injectorFactory) | |
{ | |
} | |
/// <summary> | |
/// Injects values into the properties as described by | |
/// <see cref="T:Ninject.Planning.Directives.PropertyInjectionDirective"/>s | |
/// contained in the plan. | |
/// </summary> | |
/// <param name="context">The context.</param> | |
/// <param name="reference">A reference to the instance being | |
/// activated.</param> | |
public override void Activate(IContext context, InstanceReference reference) | |
{ | |
if (this.activatedInstances.Contains(reference.Instance)) | |
{ | |
return; // "Skip" standard activation as it was already done! | |
} | |
// Keep track of non-transient activations... | |
// Note: Maybe this should be | |
// ScopeCallback == StandardScopeCallbacks.Singleton | |
if (context.Binding.ScopeCallback != StandardScopeCallbacks.Transient) | |
{ | |
this.activatedInstances.Add(reference.Instance); | |
} | |
base.Activate(context, reference); | |
} | |
/// <summary> | |
/// Contributes to the deactivation of the instance in the specified context. | |
/// </summary> | |
/// <param name="context">The context.</param> | |
/// <param name="reference">A reference to the instance being | |
/// deactivated.</param> | |
public override void Deactivate(IContext context, InstanceReference reference) | |
{ | |
this.activatedInstances.Remove(reference.Instance); | |
base.Deactivate(context, reference); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Implementation of IBuilderInternal using the N inject Framework container | |
/// </summary> | |
public class NinjectObjectBuilder : IContainer | |
{ | |
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | |
/// <summary> | |
/// The kernel hold by this object builder. | |
/// </summary> | |
private readonly IKernel kernel; | |
/// <summary> | |
/// The object builders injection propertyHeuristic for properties. | |
/// </summary> | |
private readonly IObjectBuilderPropertyHeuristic propertyHeuristic; | |
/// <summary> | |
/// Maps the supported <see cref="ComponentCallModelEnum"/> to the <see cref="StandardScopeCallbacks"/> of ninject. | |
/// </summary> | |
private readonly IDictionary<ComponentCallModelEnum, Func<IContext, object>> callModelToScopeMapping = | |
new Dictionary<ComponentCallModelEnum, Func<IContext, object>> | |
{ | |
{ ComponentCallModelEnum.Singleton, StandardScopeCallbacks.Singleton }, | |
{ ComponentCallModelEnum.Singlecall, StandardScopeCallbacks.Transient }, | |
}; | |
/// <summary> | |
/// Initializes a new instance of the <see cref="NinjectObjectBuilder"/> class. | |
/// </summary> | |
/// <remarks> | |
/// Uses the default object builder property <see cref="propertyHeuristic"/> | |
/// <see cref="ObjectBuilderPropertyHeuristic"/>. | |
/// </remarks> | |
/// <param name="kernel"> | |
/// The kernel. | |
/// </param> | |
public NinjectObjectBuilder(IKernel kernel) | |
{ | |
this.kernel = kernel; | |
this.RegisterNecessaryBindings(); | |
this.propertyHeuristic = this.kernel.Get<IObjectBuilderPropertyHeuristic>(); | |
this.AddCustomPropertyInjectionHeuristic(); | |
this.ReplacePropertyInjectionStrategyWithCustomPropertyInjectionStrategy(); | |
} | |
/// <summary> | |
/// Builds the specified type. | |
/// </summary> | |
/// <param name="typeToBuild"> | |
/// The type to build. | |
/// </param> | |
/// <returns> | |
/// An instance of the given type. | |
/// </returns> | |
public object Build(Type typeToBuild) | |
{ | |
var output = this.kernel.Get(typeToBuild); | |
return output; | |
} | |
/// <summary> | |
/// Returns a list of objects instantiated because their type is compatible with the given type. | |
/// </summary> | |
/// <param name="typeToBuild"> | |
/// The type to build. | |
/// </param> | |
/// <returns> | |
/// A list of objects | |
/// </returns> | |
public IEnumerable<object> BuildAll(Type typeToBuild) | |
{ | |
var output = this.kernel.GetAll(typeToBuild); | |
return output; | |
} | |
/// <summary> | |
/// Configures the specified component. | |
/// </summary> | |
/// <param name="component"> | |
/// The component. | |
/// </param> | |
/// <param name="callModel"> | |
/// The call model. | |
/// </param> | |
public void Configure(Type component, ComponentCallModelEnum callModel) | |
{ | |
if (this.HasComponent(component)) | |
{ | |
Log.DebugFormat( | |
CultureInfo.InvariantCulture, | |
"Skipping configuration for {0} and call model {1}", | |
component.FullName, | |
callModel); | |
return; | |
} | |
var instanceScope = this.GetInstanceScopeFrom(callModel); | |
this.BindComponentToItself(component, instanceScope); | |
this.BindAliasesOfComponentToComponent(component, instanceScope); | |
Log.DebugFormat( | |
CultureInfo.InvariantCulture, | |
"Registering configuration for {0} and call model {1}", | |
component.FullName, | |
callModel); | |
this.propertyHeuristic.RegisteredTypes.Add(component); | |
} | |
/// <summary> | |
/// Configures the property. | |
/// </summary> | |
/// <param name="component"> | |
/// The component. | |
/// </param> | |
/// <param name="property"> | |
/// The property. | |
/// </param> | |
/// <param name="value"> | |
/// The value. | |
/// </param> | |
public void ConfigureProperty(Type component, string property, object value) | |
{ | |
var bindings = this.kernel.GetBindings(component); | |
if (!bindings.Any()) | |
{ | |
throw new ArgumentException("Component not registered", "component"); | |
} | |
foreach (var binding in bindings) | |
{ | |
binding.Parameters.Add(new PropertyValue(property, value)); | |
} | |
} | |
/// <summary> | |
/// Registers the singleton. | |
/// </summary> | |
/// <param name="lookupType"> | |
/// Type lookup type. | |
/// </param> | |
/// <param name="instance"> | |
/// The instance. | |
/// </param> | |
public void RegisterSingleton(Type lookupType, object instance) | |
{ | |
this.kernel.Bind(lookupType).ToConstant(instance); | |
} | |
/// <summary> | |
/// Determines whether the specified component type has a component. | |
/// </summary> | |
/// <param name="componentType"> | |
/// Type of the component. | |
/// </param> | |
/// <returns> | |
/// <c>true</c> if the specified component type has a component; otherwise, <c>false</c>. | |
/// </returns> | |
public bool HasComponent(Type componentType) | |
{ | |
var bindings = this.kernel.GetBindings(componentType); | |
return bindings.Any(); | |
} | |
/// <summary> | |
/// Gets all service types of a given component. | |
/// </summary> | |
/// <param name="component">The component.</param> | |
/// <returns>All service types.</returns> | |
private static IEnumerable<Type> GetAllServices(Type component) | |
{ | |
return component.GetInterfaces(); | |
} | |
/// <summary> | |
/// Gets the instance scope from call model. | |
/// </summary> | |
/// <param name="callModel"> | |
/// The call model. | |
/// </param> | |
/// <returns> | |
/// The instance scope | |
/// </returns> | |
private Func<IContext, object> GetInstanceScopeFrom(ComponentCallModelEnum callModel) | |
{ | |
Func<IContext, object> scope; | |
if (!this.callModelToScopeMapping.TryGetValue(callModel, out scope)) | |
{ | |
throw new ArgumentException("The call model is not supported", "callModel"); | |
} | |
return scope; | |
} | |
/// <summary> | |
/// Binds the aliases of component to component with the given <paramref name="instanceScope"/>. | |
/// </summary> | |
/// <param name="component"> | |
/// The component. | |
/// </param> | |
/// <param name="instanceScope"> | |
/// The instance scope. | |
/// </param> | |
private void BindAliasesOfComponentToComponent(Type component, Func<IContext, object> instanceScope) | |
{ | |
var services = GetAllServices(component).Where(t => t != component); | |
foreach (var service in services) | |
{ | |
this.kernel.Bind(service).ToMethod(ctx => ctx.Kernel.Get(component)) | |
.InScope(instanceScope); | |
} | |
} | |
/// <summary> | |
/// Binds the component to itself with the given <paramref name="instanceScope"/>. | |
/// </summary> | |
/// <param name="component"> | |
/// The component. | |
/// </param> | |
/// <param name="instanceScope"> | |
/// The instance scope. | |
/// </param> | |
private void BindComponentToItself(Type component, Func<IContext, object> instanceScope) | |
{ | |
this.kernel.Bind(component).ToSelf() | |
.InScope(instanceScope); | |
} | |
/// <summary> | |
/// Adds the custom property injection heuristic. | |
/// </summary> | |
private void AddCustomPropertyInjectionHeuristic() | |
{ | |
this.kernel.Components.Get<ISelector>().InjectionHeuristics.Add( | |
this.kernel.Get<IObjectBuilderPropertyHeuristic>()); | |
} | |
/// <summary> | |
/// Registers the necessary bindings. | |
/// </summary> | |
private void RegisterNecessaryBindings() | |
{ | |
this.kernel.Bind<IContainer>().ToConstant(this).InSingletonScope(); | |
this.kernel.Bind<NewActivationPropertyInjectStrategy>().ToSelf() | |
.InSingletonScope() | |
.WithPropertyValue("Settings", ctx => ctx.Kernel.Settings); | |
this.kernel.Bind<IObjectBuilderPropertyHeuristic>().To<ObjectBuilderPropertyHeuristic>() | |
.InSingletonScope() | |
.WithPropertyValue("Settings", ctx => ctx.Kernel.Settings); | |
this.kernel.Bind<IInjectorFactory>().ToMethod(ctx => ctx.Kernel.Components.Get<IInjectorFactory>()); | |
} | |
/// <summary> | |
/// Replaces the default property injection strategy with custom property injection strategy. | |
/// </summary> | |
private void ReplacePropertyInjectionStrategyWithCustomPropertyInjectionStrategy() | |
{ | |
IList<IActivationStrategy> activationStrategies = this.kernel.Components.Get<IPipeline>().Strategies; | |
IList<IActivationStrategy> copiedStrategies = new List<IActivationStrategy>( | |
activationStrategies.Where(strategy => !strategy.GetType().Equals(typeof(PropertyInjectionStrategy))) | |
.Union(new List<IActivationStrategy> { this.kernel.Get<NewActivationPropertyInjectStrategy>() })); | |
activationStrategies.Clear(); | |
copiedStrategies.ToList().ForEach(activationStrategies.Add); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// The static class which holds <see cref="NServiceBus"/> extensions methods. | |
/// </summary> | |
public static class NinjectObjectBuilderConfig | |
{ | |
/// <summary> | |
/// Instructs <see cref="NServiceBus"/> to use the provided kernel | |
/// </summary> | |
/// <param name="config">The extended Configure.</param> | |
/// <param name="kernel">The kernel.</param> | |
/// <returns>The Configure.</returns> | |
public static Configure NinjectBuilder(this Configure config, IKernel kernel) | |
{ | |
ConfigureCommon.With(config, new NinjectObjectBuilder(kernel)); | |
return config; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Tests the behavior of the <see cref="NinjectObjectBuilder"/>. | |
/// </summary> | |
public class NinjectObjectBuilderTest | |
{ | |
private readonly IKernel kernelUsedByTestee; | |
private readonly NinjectObjectBuilder testee; | |
/// <summary> | |
/// Initializes a new instance of the <see cref="NinjectObjectBuilderTest"/> class. | |
/// </summary> | |
public NinjectObjectBuilderTest() | |
{ | |
this.kernelUsedByTestee = new StandardKernel(); | |
this.testee = new NinjectObjectBuilder(this.kernelUsedByTestee); | |
} | |
/// <summary> | |
/// TestInterface which allows to retrieve all instances implementing this interface. | |
/// </summary> | |
private interface ITestInterface | |
{ | |
} | |
/// <summary> | |
/// The constructor must register the instance of itself on the kernelUsedByTestee. | |
/// </summary> | |
[Fact] | |
public void Constructor_MustRegisterInstanceOnKernel() | |
{ | |
var container = this.kernelUsedByTestee.Get<IContainer>(); | |
Assert.NotNull(container); | |
Assert.Same(this.testee, container); | |
} | |
/// <summary> | |
/// <see cref="ObjectBuilderPropertyHeuristic"/> must be added to the <see cref="ISelector"/> because this | |
/// overrides the standard property injection behavior of n inject. | |
/// </summary> | |
[Fact] | |
public void Constructor_MustRegisterObjectBuilderPropertyHeuristic() | |
{ | |
var heuristics = this.kernelUsedByTestee.Components.Get<ISelector>().InjectionHeuristics; | |
Assert.True(heuristics.Select(heuristic => heuristic.GetType()).Contains(typeof(ObjectBuilderPropertyHeuristic))); | |
} | |
/// <summary> | |
/// The <see cref="NewActivationPropertyInjectStrategy"/> must be added to the pipeline's strategies. | |
/// </summary> | |
[Fact] | |
public void Constructor_MustRegisterNewActivationPropertyInjectionStrategy() | |
{ | |
var strategies = this.kernelUsedByTestee.Components.Get<IPipeline>().Strategies; | |
Assert.Contains(typeof(NewActivationPropertyInjectStrategy), strategies.Select(strategy => strategy.GetType())); | |
} | |
/// <summary> | |
/// All the standard strategies of ninject must be kept expect the <see cref="PropertyInjectionStrategy"/> must | |
/// be replaced. | |
/// </summary> | |
[Fact] | |
public void Constructor_MustHonorNinjectStandardStrategiesExpectPropertyStrategy() | |
{ | |
var standardKernel = new StandardKernel(); | |
var standardStrategies = standardKernel.Components.Get<IPipeline>().Strategies; | |
var standardStrategyTypes = standardStrategies.Select(strategy => strategy.GetType()); | |
var strategies = this.kernelUsedByTestee.Components.Get<IPipeline>().Strategies; | |
var strategyTypes = strategies.Select(strategy => strategy.GetType()); | |
var standardStrategyTypesWithoutPropertyInjectionStrategy = standardStrategyTypes | |
.Where(strategytype => !strategytype.Equals(typeof(PropertyInjectionStrategy))); | |
var strategyTypesWithoutNewActionavtionPropertyInjectionStrategy = strategyTypes | |
.Where(strategytype => !strategytype.Equals(typeof(NewActivationPropertyInjectStrategy))); | |
Assert.DoesNotContain(typeof(PropertyInjectionStrategy), strategyTypes); | |
Assert.Equal(standardStrategyTypesWithoutPropertyInjectionStrategy, strategyTypesWithoutNewActionavtionPropertyInjectionStrategy); | |
} | |
/// <summary> | |
/// When the bindings cannot be fulfilled an <see cref="ActivationException"/> must be thrown. | |
/// </summary> | |
[Fact] | |
public void Build_WhenNoBindingsPresent_MustThrowActivationException() | |
{ | |
Assert.Throws<ActivationException>(() => { this.testee.Build(typeof(TestClass)); }); | |
} | |
/// <summary> | |
/// When bindings are present an new instance must be build up. | |
/// </summary> | |
[Fact] | |
public void Build_WhenBindingPresent_MustCreateInstance() | |
{ | |
const string ConstructorArgument = "TestDependency"; | |
this.DefineCustomBindingsOnKernel(ConstructorArgument); | |
var testObject = this.testee.Build(typeof(TestClass)) as TestClass; | |
Assert.NotNull(testObject); | |
Assert.Equal(ConstructorArgument, testObject.Dependency.Name); | |
} | |
/// <summary> | |
/// BuildAll must throw an <see cref="ActivationException"/> when no bindings are present. | |
/// </summary> | |
[Fact] | |
public void BuildAll_WhenNoBindingsPresent_MustThrowActivationExceptionWhenIterated() | |
{ | |
Assert.Throws<ActivationException>(() => { this.testee.BuildAll(typeof(TestClass)).Any(); }); | |
} | |
/// <summary> | |
/// When bindings are present all bindings defined for the requested type must be instantiated. | |
/// </summary> | |
[Fact] | |
public void BuildAll_WhenBindingsPresent_MustCreateAvailableInstances() | |
{ | |
this.DefineCustomBindingsOnKernel("TestDependency"); | |
this.kernelUsedByTestee.Bind<ITestInterface>().ToMethod(ctx => ctx.Kernel.Get<TestClass>()); | |
this.kernelUsedByTestee.Bind<ITestInterface>().ToMethod(ctx => ctx.Kernel.Get<Dependency>()); | |
var testInstances = this.testee.BuildAll(typeof(ITestInterface)); | |
Assert.Equal(2, testInstances.Count()); | |
} | |
/// <summary> | |
/// When no bindings for a requested type are available the has component request must return | |
/// <see langword="false"/>. | |
/// </summary> | |
[Fact] | |
public void HasComponent_WhenNoBindingsPresent_MustReturnFalse() | |
{ | |
Assert.False(this.testee.HasComponent(typeof(TestClass))); | |
} | |
/// <summary> | |
/// When bindings for a requested type are available the has component request must return | |
/// <see langword="true"/>. | |
/// </summary> | |
[Fact] | |
public void HasComponent_WhenBindingsPresent_MustReturnTrue() | |
{ | |
this.DefineCustomBindingsOnKernel("TestDependency"); | |
Assert.True(this.testee.HasComponent(typeof(TestClass))); | |
} | |
/// <summary> | |
/// When registering singletons the some instance must be returned on every request. | |
/// </summary> | |
[Fact] | |
public void RegisterSingleton_MustBindToConstant() | |
{ | |
TestClass testObject = new TestClass(null); | |
this.testee.RegisterSingleton(typeof(TestClass), testObject); | |
var firstResultObject = this.kernelUsedByTestee.Get<TestClass>(); | |
var secondResultObject = this.kernelUsedByTestee.Get<TestClass>(); | |
Assert.Same(testObject, firstResultObject); | |
Assert.Same(testObject, secondResultObject); | |
} | |
/// <summary> | |
/// When no bindings are defined for a given type an argument exception must be thrown. | |
/// </summary> | |
[Fact] | |
public void ConfigureProperty_WhenNoBindingsAreDefined_MustThrowArgumentException() | |
{ | |
Assert.Throws<ArgumentException>(() => this.testee.ConfigureProperty(typeof(TestClass), "Dependency", new Dependency(null))); | |
} | |
/// <summary> | |
/// When bindings are defined for a given type a property value must be added for each binding. | |
/// </summary> | |
[Fact] | |
public void ConfigureProperty_WhenBindingsAreDefined_PropertyParameterMustBeAdded() | |
{ | |
this.DefineCustomBindingsOnKernel(string.Empty); | |
this.testee.ConfigureProperty(typeof(TestClass), "Dependency", new Dependency(null)); | |
var bindings = this.kernelUsedByTestee.GetBindings(typeof(TestClass)); | |
Assert.Equal(1, bindings.Single().Parameters.Count); | |
Assert.True(bindings.Single().Parameters.Single() is PropertyValue); | |
} | |
/// <summary> | |
/// Configuration of a component with <see cref="ComponentCallModelEnum.Singleton"/> must register type with | |
/// singleton scope. | |
/// </summary> | |
[Fact] | |
public void Configure_WithSingletonCallModel_MustRegisterSingletonScope() | |
{ | |
this.kernelUsedByTestee.Bind<Dependency>().ToSelf().WithConstructorArgument("name", string.Empty); | |
this.testee.Configure(typeof(TestClass), ComponentCallModelEnum.Singleton); | |
var firstInstance = this.kernelUsedByTestee.Get<TestClass>(); | |
var secondInstance = this.kernelUsedByTestee.Get<TestClass>(); | |
Assert.Same(firstInstance, secondInstance); | |
} | |
/// <summary> | |
/// Configuration of a component with <see cref="ComponentCallModelEnum.Singlecall"/> must register type with | |
/// transient scope. | |
/// </summary> | |
[Fact] | |
public void Configure_WithSingleCallModel_MustRegisterTransientScope() | |
{ | |
this.kernelUsedByTestee.Bind<Dependency>().ToSelf().WithConstructorArgument("name", string.Empty); | |
this.testee.Configure(typeof(TestClass), ComponentCallModelEnum.Singlecall); | |
var firstInstance = this.kernelUsedByTestee.Get<TestClass>(); | |
var secondInstance = this.kernelUsedByTestee.Get<TestClass>(); | |
Assert.NotSame(firstInstance, secondInstance); | |
} | |
/// <summary> | |
/// Configuration of a call model which is not supported must throw <see cref="ArgumentException"/>. | |
/// </summary> | |
[Fact] | |
public void Configure_WithUnsupportedCallModel_MustThrowArgumentException() | |
{ | |
Assert.Throws<ArgumentException>(() => this.testee.Configure(typeof(TestClass), ComponentCallModelEnum.None)); | |
} | |
/// <summary> | |
/// Properties set on duplicate registrations should not be discarded. | |
/// </summary> | |
/// <remarks>These tests are from NServiceBus tests for object builders.</remarks> | |
[Fact] | |
public void Properties_SetOnDuplicateRegistrations_ShouldNotBeDiscarded() | |
{ | |
this.testee.Configure(typeof(DuplicateClass), ComponentCallModelEnum.Singleton); | |
this.testee.ConfigureProperty(typeof(DuplicateClass), "SomeProperty", true); | |
this.testee.Configure(typeof(DuplicateClass), ComponentCallModelEnum.Singleton); | |
this.testee.ConfigureProperty(typeof(DuplicateClass), "AnotherProperty", true); | |
var component = (DuplicateClass) this.testee.Build(typeof(DuplicateClass)); | |
Assert.True(component.SomeProperty); | |
Assert.True(component.AnotherProperty); | |
} | |
/// <summary> | |
/// Multiple registrations of the same component should be allowed. | |
/// </summary> | |
/// <remarks>These tests are from NServiceBus tests for object builders.</remarks> | |
[Fact] | |
public void MultipleRegistrationsOfTheSameComponent_ShouldBeAllowed() | |
{ | |
this.testee.Configure(typeof(DuplicateClass), ComponentCallModelEnum.Singlecall); | |
this.testee.Configure(typeof(DuplicateClass), ComponentCallModelEnum.Singlecall); | |
var builded = this.testee.BuildAll(typeof(DuplicateClass)); | |
Assert.Equal(1, builded.Count()); | |
} | |
/// <summary> | |
/// Defines the custom bindings on the kernelUsedByTestee. | |
/// </summary> | |
/// <param name="constructorArgument">The constructor argument.</param> | |
private void DefineCustomBindingsOnKernel(string constructorArgument) | |
{ | |
this.kernelUsedByTestee.Bind<TestClass>().ToSelf(); | |
this.kernelUsedByTestee.Bind<Dependency>().ToSelf().WithConstructorArgument("name", constructorArgument); | |
} | |
/// <summary> | |
/// Test class from NServiceBus sources. | |
/// </summary> | |
private class DuplicateClass | |
{ | |
/// <summary> | |
/// Gets or sets a value indicating whether some property is set. | |
/// </summary> | |
/// <value><c>true</c> if some property is set; otherwise, <c>false</c>.</value> | |
public bool SomeProperty { get; set; } | |
/// <summary> | |
/// Gets or sets a value indicating whether another property is set. | |
/// </summary> | |
/// <value><c>true</c> if another property is set; otherwise, <c>false</c>.</value> | |
public bool AnotherProperty { get; set; } | |
} | |
/// <summary> | |
/// Test class which is only used in this test. | |
/// </summary> | |
private class TestClass : ITestInterface | |
{ | |
/// <summary> | |
/// Initializes a new instance of the <see cref="TestClass"/> class. | |
/// </summary> | |
/// <param name="dependency">The dependency.</param> | |
public TestClass(Dependency dependency) | |
{ | |
this.Dependency = dependency; | |
} | |
/// <summary> | |
/// Gets the dependency. | |
/// </summary> | |
/// <value>The dependency.</value> | |
public Dependency Dependency | |
{ | |
get; | |
private set; | |
} | |
} | |
/// <summary> | |
/// Dependency class which is only used in this test. | |
/// </summary> | |
private class Dependency : ITestInterface | |
{ | |
/// <summary> | |
/// Initializes a new instance of the <see cref="Dependency"/> class. | |
/// </summary> | |
/// <param name="name">The name of this dependency.</param> | |
public Dependency(string name) | |
{ | |
this.Name = name; | |
} | |
/// <summary> | |
/// Gets the name. | |
/// </summary> | |
/// <value>The name of this dependency.</value> | |
public string Name | |
{ | |
get; | |
private set; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Implements an more aggressive injection heuristic. | |
/// </summary> | |
internal class ObjectBuilderPropertyHeuristic : IObjectBuilderPropertyHeuristic | |
{ | |
/// <summary> | |
/// Initializes a new instance of the <see cref="ObjectBuilderPropertyHeuristic"/> class. | |
/// </summary> | |
public ObjectBuilderPropertyHeuristic() | |
{ | |
this.RegisteredTypes = new List<Type>(); | |
} | |
/// <summary> | |
/// Gets the registered types. | |
/// </summary> | |
/// <value>The registered types.</value> | |
public IList<Type> RegisteredTypes { get; private set; } | |
/// <summary> | |
/// Gets or sets the settings. | |
/// </summary> | |
/// <value>The settings.</value> | |
public INinjectSettings Settings | |
{ | |
get; | |
set; | |
} | |
/// <summary> | |
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. | |
/// </summary> | |
public void Dispose() | |
{ | |
this.Dispose(true); | |
GC.SuppressFinalize(this); | |
} | |
/// <summary> | |
/// Determines whether a given type should be injected. | |
/// </summary> | |
/// <param name="member">The member info to check.</param> | |
/// <returns><see langword="true"/> if a given type needs to be injected; otherwise <see langword="false"/>. | |
/// </returns> | |
public bool ShouldInject(MemberInfo member) | |
{ | |
var propertyInfo = member as PropertyInfo; | |
if (propertyInfo == null) | |
{ | |
return false; | |
} | |
return this.RegisteredTypes.Where(x => propertyInfo.DeclaringType.IsAssignableFrom(x)).Any() | |
&& this.RegisteredTypes.Where(x => propertyInfo.PropertyType.IsAssignableFrom(x)).Any() | |
&& propertyInfo.CanWrite; | |
} | |
/// <summary> | |
/// Releases unmanaged and - optionally - managed resources | |
/// </summary> | |
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release | |
/// only unmanaged resources.</param> | |
protected virtual void Dispose(bool disposing) | |
{ | |
this.RegisteredTypes.Clear(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment