Skip to content

Commit

Permalink
Work around for Ninject bug
Browse files Browse the repository at this point in the history
Fixes #801

See ninject/Ninject#235 for more details
  • Loading branch information
einari committed Apr 12, 2017
1 parent 5f7d815 commit 324ee57
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Source/Bifrost.Ninject/Bifrost.Ninject.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@
<ProjectReference Include="..\Bifrost\Bifrost.csproj" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<Compile Remove="**/netstandard/**/*.cs" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'net461' ">
<Compile Remove="**/net4x/**/*.cs" />
</ItemGroup>


<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<PackageReference Include="Ninject" Version="3.2.2" />
<Reference Include="System" />
Expand Down
5 changes: 5 additions & 0 deletions Source/Bifrost.Ninject/Container.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public Container(IKernel kernel)
{
Kernel = kernel;
_boundServices = new List<Type>();

#if (!NET461)
kernel.Components.Remove<global::Ninject.Planning.Strategies.IPlanningStrategy, global::Ninject.Planning.Strategies.ConstructorReflectionStrategy>();
kernel.Components.Add<global::Ninject.Planning.Strategies.IPlanningStrategy, ConstructorReflectionStrategy>();
#endif
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) 2008-2017 Dolittle. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System.Linq;
using System.Reflection;
using Ninject.Injection;
using Ninject.Planning.Targets;

namespace Bifrost.Ninject
{
/// <summary>
/// Represents an implementation of <see cref="global::Ninject.Planning.Directives.ConstructorInjectionDirective"/> for
/// fixing an activation bug inside Ninject (https://github.com/ninject/Ninject/issues/235)
/// </summary>
public class ConstructorInjectionDirective : global::Ninject.Planning.Directives.ConstructorInjectionDirective
{
/// <summary>
///
/// </summary>
/// <param name="constructor"></param>
/// <param name="injector"></param>
public ConstructorInjectionDirective(ConstructorInfo constructor, ConstructorInjector injector)
: base(constructor, injector)
{

}

/// <inheritdoc/>
protected override ITarget[] CreateTargetsFromParameters(ConstructorInfo method)
{
return method.GetParameters().Select(parameter => new ParameterTarget(method, parameter)).ToArray();
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) 2008-2017 Dolittle. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System.Reflection;
using Ninject.Components;
using Ninject.Infrastructure.Language;
using Ninject.Injection;
using Ninject.Planning;
using Ninject.Planning.Strategies;
using Ninject.Selection;

namespace Bifrost.Ninject
{
/// <summary>
/// Represents an implementation of <see cref="IPlanningStrategy"/> to work around a bug related
/// to wether or not a parameter has default value inside Ninject (https://github.com/ninject/Ninject/issues/235)
/// </summary>
public class ConstructorReflectionStrategy : NinjectComponent, IPlanningStrategy
{
/// <summary>
/// Initializes a new instance of <see cref="ConstructorReflectionStrategy"/>
/// </summary>
/// <param name="selector"><see cref="ISelector"/> to use</param>
/// <param name="injectorFactory"><see cref="IInjectorFactory"/> to use</param>
public ConstructorReflectionStrategy(ISelector selector, IInjectorFactory injectorFactory)
{
Selector = selector;
InjectorFactory = injectorFactory;
}

/// <inheritdoc/>
public ISelector Selector { get; private set; }

/// <inheritdoc/>
public IInjectorFactory InjectorFactory { get; private set; }

/// <inheritdoc/>
public void Execute(IPlan plan)
{
var constructors = this.Selector.SelectConstructorsForInjection(plan.Type);
if (constructors == null)
{
return;
}

foreach (ConstructorInfo constructor in constructors)
{
var hasInjectAttribute = constructor.HasAttribute(this.Settings.InjectAttribute);
var directive = new ConstructorInjectionDirective(constructor, this.InjectorFactory.Create(constructor))
{
HasInjectAttribute = hasInjectAttribute
};

plan.Add(directive);
}
}

}
}
55 changes: 55 additions & 0 deletions Source/Bifrost.Ninject/netstandard/ParameterTarget.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) 2008-2017 Dolittle. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using System;
using System.Reflection;
using Ninject.Planning.Targets;

namespace Bifrost.Ninject
{
/// <summary>
/// Represents an implementation of <see cref="Target{T}"/> for working around a bug in
/// Ninject (https://github.com/ninject/Ninject/issues/235) related to HasDefaultValue
/// returning true when it should be false
/// </summary>
public class ParameterTarget : Target<ParameterInfo>
{
Lazy<object> _defaultValue;
bool _hasDefaultValue;

/// <summary>
/// Initializes a new instance of the <see cref="ParameterTarget"/> class.
/// </summary>
/// <param name="method">The method that defines the parameter.</param>
/// <param name="site">The parameter that this target represents.</param>
public ParameterTarget(MethodBase method, ParameterInfo site)
: base(method, site)
{
_hasDefaultValue = site.HasDefaultValue;
_defaultValue = new Lazy<object>(() => site.DefaultValue);
}

/// <inheritdoc/>
public override string Name
{
get { return Site.Name; }
}

/// <inheritdoc/>
public override Type Type
{
get { return Site.ParameterType; }
}

/// <inheritdoc/>
public override bool HasDefaultValue => _hasDefaultValue;

/// <inheritdoc/>
public override object DefaultValue
{
get { return HasDefaultValue ? _defaultValue.Value : base.DefaultValue; }
}

}
}

0 comments on commit 324ee57

Please sign in to comment.