Ninject selecting parameterless constructor when using implicit self-binding - dependency-injection

I am using Ninject version 3 in an MVVM-type scenario in a .NET WPF application. In a particular instance I am using a class to act as coordinator between the view and its view model, meaning the coordinator class is created first and the view and view model (along with other needed services) are injected into it.
I have bindings for the services, but I have not created explicit bindings for the view/view model classes, instead relying on Ninject's implicit self-binding since these are concrete types and not interfaces.
A conceptual version of this scenario in a console app is shown below:
class Program
{
static void Main(string[] args)
{
StandardKernel kernel = new StandardKernel();
kernel.Bind<IViewService>().To<ViewService>();
//kernel.Bind<View>().ToSelf();
//kernel.Bind<ViewModel>().ToSelf();
ViewCoordinator viewCoordinator = kernel.Get<ViewCoordinator>();
}
}
public class View
{
}
public class ViewModel
{
}
public interface IViewService
{
}
public class ViewService : IViewService
{
}
public class ViewCoordinator
{
public ViewCoordinator()
{
}
public ViewCoordinator(View view, ViewModel viewModel, IViewService viewService)
{
}
}
If you run this code as-is, the kernel.Get<> call will instantiate the ViewCoordinator class using the parameterless constructor instead of the one with the dependencies. However, if you remove the parameterless constructor, Ninject will successfully instantiate the class with the other constructor. This is surprising since Ninject will typically use the constructor with the most arguments that it can satisfy.
Clearly it can satisfy them all thanks to implicit self-binding. But if it doesn't have an explicit binding for one of the arguments it seems to first look for alternate constructors it can use before checking to see if it can use implicit self-binding. If you uncomment the explicit Bind<>().ToSelf() lines, the ViewController class will instantiate correctly even if the parameterless constructor is present.
I don't really want to have to add explicit self-bindings for all the views and view models that may need this (even though I know that burden can be lessened by using convention-based registration). Is this behavior by design? Is there any way to tell Ninject to check for implicit self-binding before checking for other usable constructors?
UPDATE
Based on cvbarros' answer I was able to get this to work by doing my own implementation of IConstructorScorer. Here's the changes I made to the existing code to get it to work:
using Ninject.Selection.Heuristics;
class Program
{
static void Main(string[] args)
{
StandardKernel kernel = new StandardKernel();
kernel.Components.RemoveAll<IConstructorScorer>();
kernel.Components.Add<IConstructorScorer, MyConstructorScorer>();
kernel.Bind<IViewService>().To<ViewService>();
ViewCoordinator viewCoordinator = kernel.Get<ViewCoordinator>();
}
}
using System.Collections;
using System.Linq;
using Ninject.Activation;
using Ninject.Planning.Targets;
using Ninject.Selection.Heuristics;
public class MyConstructorScorer : StandardConstructorScorer
{
protected override bool BindingExists(IContext context, ITarget target)
{
bool bindingExists = base.BindingExists(context, target);
if (!(bindingExists))
{
Type targetType = this.GetTargetType(target);
bindingExists = (
!targetType.IsInterface
&& !targetType.IsAbstract
&& !targetType.IsValueType
&& targetType != typeof(string)
&& !targetType.ContainsGenericParameters
);
}
return bindingExists;
}
private Type GetTargetType(ITarget target)
{
var targetType = target.Type;
if (targetType.IsArray)
{
targetType = targetType.GetElementType();
}
if (targetType.IsGenericType && targetType.GetInterfaces().Any(type => type == typeof(IEnumerable)))
{
targetType = targetType.GetGenericArguments()[0];
}
return targetType;
}
}
The new scorer just sees if a BindingExists call failed by overriding the BindingExists method and if so it checks to see if the type is implicitly self-bindable. If it is, it returns true which indicates to Ninject that there is a valid binding for that type.
The code making this check is copied from the SelfBindingResolver class in the Ninject source code. The GetTargetType code had to be copied from the StandardConstructorScorer since it's declared there as private instead of protected.
My application is now working correctly and so far I haven't seen any negative side effects from making this change. Although if anyone knows of any problems this could cause I would welcome further input.

By default, Ninject will use the constructor with most bindings available if and only if those bindings are defined (in your case they are implicit). Self-bindable types do not weight when selecting which constructor to use.
You can mark which constructor you want to use by applying the [Inject] attribute to it, this will ensure that constructor is selected.
If you don't want that, you can examine StandardConstructorScorer to see if that will fit your needs. If not, you can replace the IConstructorScorer component of the Kernel with your own implementation.

Related

How to dynamically instantiate a proxy class?

I have used Castle.DynamicProxy to create an interceptor that implements IInterceptor. This interceptor does some work related with logging.
I have successfully injected this into multiple classes using the default Microsoft Dependency Injection and I also was able to do so using Autofac.
Microsoft Dependency Injection:
public static void AddLoggedScoped<TService, TImplementation>(this IServiceCollection pServices)
where TService : class
where TImplementation : class, TService
{
pServices.TryAddScoped<IProxyGenerator, ProxyGenerator>();
pServices.AddScoped<TImplementation>();
pServices.TryAddTransient<LoggingInterceptor>();
pServices.AddScoped(provider =>
{
var proxyGenerator = provider.GetRequiredService<IProxyGenerator>();
var service = provider.GetRequiredService<TImplementation>();
var interceptor = provider.GetRequiredService<LoggingInterceptor>();
return proxyGenerator.CreateInterfaceProxyWithTarget<TService>(service, interceptor);
});
}
Autofac Dependency Injection:
builder.RegisterType<DITest>( ).As<IDITest>()
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(LoggingInterceptorAdapter<LoggingInterceptor>));
Despite this I would also like to inject it in classes dynamically instantiated (for instances, classes that are instantiated accordingly to a value - factory pattern). My factory instantiates different concretizations of an interface depending on a value provided by parameter. Something along these lines:
public IApple Create(string color)
{
IApple fruit;
switch (color)
{
case "green":
fruit = new GreenApple();
break;
case "red":
fruit = new RedApple();
}
return fruit;
}
The interface IFruit looks like these:
public interface IFruit
{
void Cut();
void Eat();
string GetNutrionalInfo();
}
What I am trying to achieve is a way to inject/add an interceptor to the concretization of RedApple() that would allow me to know when methods such as redApple.Cut() are called.
What is the best way to do so? I was under the impression that Autofac would allow this, but I have not been successful.
What you will need to do is update your factory to use service location instead of directly constructing things. Basically, instead of using new, you'll need to use Autofac or Microsoft DI (assuming Autofac is configured as the backing container) to resolve the thing.
First, whenever you need your factory, make sure you are injecting it and not just calling new. Everything involved in this chain needs to go through Autofac.
public class UsesTheFactory
{
private IFactory _factory;
public UsesTheFactory(IFactory factory)
{
this._factory = factory;
}
}
You will, of course, need to register the thing that uses the factory.
builder.RegisterType<UsesTheFactory>();
Next, inject the lifetime scope into the factory and use it for service location. This is how you get the proxy and all that into the created objects.
public class MyFactory : IFactory
{
private readonly ILifetimeScope _scope;
public MyFactory(ILifetimeScope scope)
{
this._scope = scope;
}
public IApple Create(string color)
{
IApple fruit;
switch (color)
{
case "green":
fruit = this._scope.Resolve<GreenApple>();
break;
case "red":
fruit = this._scope.Resolve<RedApple>();
}
return fruit;
}
}
You'll need to register the factory and the things that the factory needs to resolve.
builder.RegisterType<MyFactory>().As<IFactory>();
builder.RegisterType<RedApple>();
builder.RegisterType<GreenApple>();
Finally, whenever you need something that uses the factory, that thing needs to be resolved. In this example, you can't really ever just new UsesTheFactory() - you have to resolve it (or have it injected into something else).
var builder = new ContainerBuilder();
builder.RegisterType<UsesTheFactory>();
builder.RegisterType<MyFactory>().As<IFactory>();
builder.RegisterType<RedApple>();
builder.RegisterType<GreenApple>();
var container = builder.Build();
using var scope = container.BeginLifetimeScope();
var user = scope.Resolve<UsesTheFactory>();
user.DoSomethingThatCallsTheFactory();
The key principle is that if you need that proxy injected anywhere in the pipeline, you can't use new. Full stop. If you need that thing, it needs to flow through Autofac somehow.

servicestack with funq - autowiring by convention

I have a service which takes an IMyDependency in its constructor. IMyDependency, MyDependency and the service all live in the same assembly. MyDependency has a single, public, parameterless constructor.
To my surprise, this did not work:
container.RegisterAutoWired<IMyDependency>();
It throws a "System.NullReferenceException".
It works if I do this:
container.RegisterAutoWiredAs<MyDependency, IMyDependency>();
But then, so does this:
container.RegisterAs<MyDependency, IMyDependency>();
So what is the difference? If 'auto wiring' cannot find a concrete implementation, and it makes no difference to whether services requiring the dependency can be resolved, then what is auto wiring?
Is Funq supposed to be able to find your concrete implementations by convention? If so, what is that convention, if not same-named-ness?
Thanks.
Do you mean "how can I implement a solution to search through assemblies and automatically register classes in ServiceStack IOC based on a convention?"
If so, I might have a solution for you:
Create an interface that your inject-able classes will implement.
Have your inject-able classes implement that interface.
In the boot-strapping code use reflection to search your assemblies and get a list of all of the classes that implement the inject-able interface.
Use reflection to get the class name and interface based on your conventions.
Call the ServiceStack IOC method RegisterAutoWiredType and pass in the class and interface to register them.
For example if our naming convention is ClassName IClassName:
private static void RegisterCustomTypes(Container container)
{
//Get the Assembly Where the injectable classes are located.
var assembly = Assembly.GetAssembly(typeof(IInjectable));
//Get the injectable classes
var types =assembly.GetTypes()
.Where(m => m.IsClass && m.GetInterface("IInjectable") != null);
//loop through the injectable classes
foreach (var theType in types)
{
//set up the naming convention
var className = theType.Name;
var interfaceName = string.Concat("I", className);
//create the interface based on the naming convention
var theInterface = theType.GetInterface(interfaceName);
//register the type with the convention
container.RegisterAutoWiredType(theType, theInterface);
}
}
public interface IInjectable
{
}
//This class can be injected
public interface ITestManager : IInjectable
{
void Execute(int id);
}
public class TestManager : ITestManager
{
public void Execute(int id)
{
throw new System.NotImplementedException();
}
}
For simple queries like this it's best to just contact the source, e.g. here is the source code for RegisterAutoWired:
public IRegistration<T> RegisterAutoWired<T>()
{
var serviceFactory = GenerateAutoWireFn<T>();
return this.Register(serviceFactory);
}
It generates an auto-wired factory over a Concrete implementation. An interface has no implementation, it needs to be a concrete class.
And the source code for RegisterAs:
public IRegistration<TAs> RegisterAs<T, TAs>() where T : TAs
{
return this.RegisterAutoWiredAs<T, TAs>();
}
Which is just a shorter alias you can use instead of RegisterAutoWiredAs.

Injecting multiple constructor parameters of the same type with Ninject 2.0

I'm using Ninject 2.0 to handle DI in one of my apps and I've come across something that's confusing me. Having zero documentation doesn't help too much either to be honest.
Say I have a constructor with the signature -
ctor(IServiceFactory factory1, IServiceFactory factory2)
{
this.factory1 = factory1;
this.factory2 = factory2;
}
Although these two services implement the same interface, they are quite different implementations and are used at different times so I don't want to inject an IEnumerable<IServiceFactory>.
My question is, when I'm binding the instances, how do I tell Ninject what to inject for each?
Thanks in advance.
Update
For the sake of anyone wanting to see the code would end up after reading Remo's links,...Here it is in brief. (I never realised C# had parameter attributes!)
//abstract factory
public interface IServiceFactory
{
Service Create();
}
//concrete factories
public class Service1Factory : IServiceFactory
{
public IService Create()
{
return new Service1();
}
}
public class Service2Factory : IServiceFactory
{
public IService Create()
{
return new Service2();
}
}
//Binding Module (in composition root)
public class ServiceFactoryModule : NinjectModule
{
public override void Load()
{
Bind<IServiceFactory>()
.To<Service1Factory>()
.Named("Service1");
Bind<IServiceFactory>()
.To<Service2Factory>()
.Named("Service2");
}
}
//consumer of bindings
public class Consumer(
[Named("Service1")] service1Factory,
[Named("Service2")] service2Factory)
{
}
First of all you have to ask yourself if using the same interface is correct if the implementations need to do a completely different thing. Normally, the interface is the contract between the consumer and the implementation. So if the consumer expects different things then you might consider to define different interfaces.
If you decide to stay with the same interface than you have to use conditional bindings. See the documentation about how this is done:
https://github.com/ninject/ninject/wiki/Contextual-Binding
https://github.com/ninject/ninject/wiki/Conventions-Based-Binding

Ninject binds to the wrong anonymous method when there is more than one method bound type

I am building a framework that I don't want to couple to a particular IOC container so have created a layer on top of Ninject / structuremap etc.
I have a binding class that accepts a Func to allow binding to a method.
For example
public class Binding
{
public Type Source { get; set; }
public Func<object> Method {get; set; }
public Scope { get; set; }
}
If I have a binding like...
var binding = new Binding() {
Source = typeof(IRepository),
Method = () => new Repository(new LinqToSqlRepository(connectionString)),
Scope = Scope.HttpRequest
};
The framework wrapping Ninject creates Ninject bindings for my generic binding like this
Module :NinjectModule
{
IList<Binding> _Bindings;
public Module(IList<Binding> bindings)
{
_Bindings = bindings;
}
public override void Load() {
foreach (var binding in _Bindings) {
switch(binding.Scope) {
case IocScope.HttpRequest:
Bind(binding.Source).ToMethod(c => binding.Method()).InRequestScope();
break;
// ... omitted for brevity
}
}
}
}
This works fine when there is only one binding being bound to a method. When there are multiple bindings being bound within the same module to methods however the incorrect type is returned. From debugging, it looks as if the last binding is always used.
Thus the problem with an example;
var binding1 = new Binding() {
Source = typeof(IRepository),
Method = () => new Repository(new LinqToSqlRepository(connectionString)),
Scope = Scope.HttpRequest
};
var binding2 = new Binding() {
Source = typeof(ICalendar),
Method = () => new MvcCalendar( ..... )
Scope = Scope.HttpRequest
};
At runtime when Ninject is requested to new up an MVC Controller which takes in an IRepository and an ICalendar, I receive a type conversion error saying that a MvcCalendar cannot be converted to an IRepository. I have discovered that for some reason the last binding is always being returned for the first requested type.
This is a highly simplified version of what is really going on to try and highlight the actual issue, the wrong method being bound to a requested type when there are multiple method bindings. I hope this still explains the issue though.
This appears to be related to some sort of closure scoping issue. I also wonder whether Ninject is getting is getting confused by the Func instead of Func usage.
Unit Test Example
Here is a test module I load into my custom IOC container. This does not depend on any particular IOC framework. When I instantiate a NinjectIocContainer to handle the DI, the internal binding of this in Ninject occurs as example further up (see NinjectModule)
public class MultipleMethodBoundTypesModule : IocModule
{
public override void Load()
{
Bind<IPerson>().To(() => new Person()).In(IocScope.Transient);
Bind<IRobot>().To(() => new Robot(new Person())).In(IocScope.Transient);
}
}
Here is a simple test that tries to retrieve each of the types.
[Test]
public void Expect_That_Multiple_Method_Bound_Types_Can_Exist_Within_The_Same_Module()
{
// arrange
var container = Get_Container_With_Module(new MultipleMethodBoundTypesModule());
// act
var person = container.Get<IPerson>();
var robot = container.Get<IRobot>();
// assert
Assert.IsNotNull(person);
Assert.IsNotNull(robot);
}
As explained eariler, this throws a type conversion where the last closure (for the robot) is being bound to a person.
TestCase 'Ioc.Test.NinjectContainerTest.Expect_That_Multiple_Method_Bound_Types_Can_Exist_Within_The_Same_Module'
failed: System.InvalidCastException : Unable to cast object of type 'Ioc.Test.Robot' to type 'Ioc.Test.IPerson'.
at System.Linq.Enumerable.d__b11.MoveNext()
at System.Linq.Enumerable.Single[TSource](IEnumerable1 source)
at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters)
NinjectIocContainer.cs(40,0): at Ioc.Ninject.NinjectIocContainer.GetTInstance
IocTestBase.cs(149,0): at Ioc.Test.IocTestBase.Expect_That_Multiple_Method_Bound_Types_Can_Exist_Within_The_Same_Module()
In the snippet:
Bind(binding.Source).ToMethod(binding.Method()).InRequestScope();
You're dereferencing the Method bit. You want to be doing that as either binding.Method or ()=>binding.Method() (the former may not unambiguously be inferrable based on the C# type inference rules).
You mentioned this is heavily stripped down from your real code. As a result, this may not be the actual issue. I'd still be betting on some form of closure confusion though (see the section Comparing capture strategies: complexity vs power in this CSID excerpt for a nice walkthrough).
You also probably meant to use .InScope(binding.Scope) rather than .InRequestScope() too,.

Best practices: Calling GetInstance method to instantiate object

Lets discuss one thing:
I have some simple interface:
public interface ICar
{
void StartEngine();
void StopEngine();
}
public interface IRadio
{
//doesn't matter
}
and some implementation:
public class SportCar : ICar
{
private IRadio radio;
public SportCar(IRadio radioObj)
{
radio = radioObj;
}
//all the rest goes here
}
also we have our StructureMap initialization code, and we calling it on Program initialization:
private void InitializeStructureMap()
{
ObjectFactory.Initialize(x=>
{
x.For<ICar>.Use<SportCar>();
x.For<IRadio>.Use<CarAudioSystem>();
});
}
And my question is: what is the best practice to instantiate SportCar? Is calling:
ObjectFactory.GetInstance<ICar>()
a good practice (now I don't now other way to resolve this)?
ObjectFactory.GetInstance is your starting point, that is what you use to resolve the first object in the hierarcy.
This is how i start my WinForms applications, the same technique should apply to WebForms, Windows Services and Console Applications:
var main = ObjectFactory.GetInstance<Main>();
Application.Run(main);
For ASP.NET MVC the framework allows you to register a factory that creates your controllers, but even in that factory you would call ObjectFactory.GetInstance to instanciate your controller.
As a side note:
When you do initialization, you don't explicitly need to map ICar to SportCar unless you have multiple ICar implementations, you can just do
x.Scan(a => { a.TheCallingAssembly(); a.WithDefaultConventions(); });
which wil map your interfaces with default implementations.

Resources