Constructor injection with Func on Ninject - dependency-injection

I'm using a Ninject module to bind different types to their corresponding interfaces.
Injection will take place inside a class's constructor. The problem is that the class has another constructor with a signature including Func.
Ninject is confused and throws this at me:
Error activating ClassTest using implicit self-binding of ClassTest. Several constructors have the same priority. Please specify the constructor using ToConstructor syntax or add an Inject attribute.
See below how the binding is done and how I do the injection:
this.Bind<InterfaceA>().To<ClassA>();
...
public class ClassTest
{
public ClassTest(InterfaceA a)
{
}
public ClassTest(Func<ClassB> funcB)
{
}
}
...
var giveMeTest = kernel.Get<ClassTest>(); // exception thrown
}
It seems that Func is the culprit here, can you please explain me why Ninject gets confused?
Thanks

Best you delete all unused constructors. There is no reason for adding constructors that are never used. If you really need multiple constructors then you have to tell Ninject which one to pick, e.g.:
Bind<ClassTest>().ToConstructor(x => new ClassTest(x.Inject<InterfaceA>())).Named("A");
Bind<ClassTest>().ToConstructor(x => new ClassTest(x.Inject<Func<ClassB>>())).Named("B");
kernel.Get<ClassTest>("A");
kernel.Get<ClassTest>("B");

Related

Asp.net core 2.0 AutoMapper IValueResolver dependency injection

I have tried most of the examples in the Google Results, Stackoverflow and in AutoMapper. But was not able to get the IValueResolverdependancy injection to work.
I have below service
public class StorageService : IStorageService
{
private readonly BlobServiceSettings _blobServiceSettings;
public StorageService(IOptions<BlobServiceSettings> blobServiceSettings)
{
_blobServiceSettings = blobServiceSettings.Value;
}
// some methods I need
}
This is my profile
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Building, BuildingEnvelope>(MemberList.None)
.ForMember(dest => dest.ImageUrl, opt => opt.ResolveUsing<BuildingImageUrlResolver>());
}
}
this is my IValueResolver
public class BuildingImageUrlResolver : IValueResolver<Building, BuildingEnvelope, string>
{
private readonly IStorageService _storageService;
public BuildingImageUrlResolver(IStorageService storageService)
{
_storageService = storageService;
}
public string Resolve(Building entity, BuildingEnvelope envelope, string member, ResolutionContext context)
{
return _storageService.MyMethod(entity.ImageFileName);
}
}
I get the below error in my inner exception
No parameterless constructor defined for this object.
Not sure what I am doing wrong.
Thanks in advance
Neo
Lucian's suggestion is correct -- the AutoMapper.Extensions.Microsoft.DependencyInjection package is the way to go. Even if you don't want to use it, you'll have to do something similar.
I've had this very same problem and by using the extensions, you just modify the entrypoint from which you register AutoMapper and its configuration.
What the extensions do (source) is:
Initializes Automapper with the configuration provided
It scans for all classes you have that you could be implementing with dependency injection and registers them as transient, looking for implementations of the following:
IValueResolver
IMemberValueResolver
ITypeConverter
IMappingAction
The assemblies that it will scan actually depend on the parameters that you provide on the call.
If any of these can be actually instantiated, then they will be registered as transient implementation.
And just like that, AutoMapper will request instances of these to the service provider, which will resolve them, and to do that, it will also resolve any pending dependencies.
Note that this is actually very simple -- the most difficult part is scanning the right assemblies and registering the right classes. You can do it manually too, but these extensions already take care of it for you.
Mind you, even when reflection has been improved a lot, this process is relatively slow, so try not to abuse it too much (for instance, in tests).
Finally, if none of that works for you, remember that you need to setup AutoMapper to use the dependency injection resolver too:
automapperConfiguration.ConstructServicesUsing(serviceProvider.GetService);

Inject custom connection string into Entity Framework's DbContext

I want to inject a custom connection string into my EF context instead of using the connection string in my web.config. The idea is to move all database related logic off of my MVC project into a separate layer. I also want this layer to be responsible for the proper connection strings instead of my web applications.
The services currently using the context are calling the default constructor:
using (var context = new MyDbContext()) {
//...
}
The default constructor is internally calling DbContext with the name of the connection string from the web.config:
public partial class MyDbContext : DbContext
{
public MyDbContext()
: base("name=MyDbContext")
{
}
//...
}
In order to inject my custom connection string I would need an overloaded constructor which takes the connection string as an argument. Unfortunately there is not such a constructor provided.
It is obvious that adding the constructor overload manually right inside the MyDbContext class would be a very bad idea, since this class is auto-generated and will be overwritten any time soon. Let's not talk about this any more, it's forbidden. Period.
Since MyDbContext is a partial class, one could add the additional constructor in a separate class file partial class MyDbContext, but this seems smelly either. I don't know why, but my brain says bad idea.
After some investigation I found out, that one can tell EF to include this additional constructor by editing the T4 template Model.Context.tt which is a mix of C# and some template markup. Here is the original constructor:
public <#=Code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
<#
WriteLazyLoadingEnabled(container);
#>
}
It is obviously easy to add similar logic to generate an overloaded constructor containing the connection string:
public <#=Code.Escape(container)#>(string nameOrConnectionString)
: base(nameOrConnectionString)
{
<#
WriteLazyLoadingEnabled(container);
#>
}
I tried this and noticed, that both re-generating the model classes and updating the model from DB will not affect the T4 template, thus the additional constructor will always be there. Good! At first glance this looks like a suitable solution, but...
And here is my question: Is that really a good solution?
Let's compare the three options again:
Edit the auto-generated class (ok, we agreed to forget about this)
Add the constructor in a partial class file
Edit the T4 template to tell EF to generate the additional constructor
From these three options the third seems to me to be the most convenient and clean solution. What is your opinion? Has someone a good reason, why this would be a bad idea? Are there more options to inject connection strings, maybe using a custom connectionFactory? If so, how would I do that?
Like #shaft proposed, I replaced my T4 template approach to using a partial class. As it turned out, this is indeed a lot simpler and intuitive, than any other solution I currently know of.
The auto-generated class looks like:
public partial class MyDbContext : DbContext
{
public MyDbContext() : base("name=MyDbContext")
{
}
//...
}
I just added another partial class of the same name. Issue solved.
public partial class MyDbContext
{
public MyDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
}
}
From the 3 options you provide I'd rather choose option 2. Hasn't the partial keyword been introduced to solve the problem with autogenerated files? Using T4 templates brings additional complexity in my opinion, the maintaining developer has than to understand one more thing (Not everyone is familiar with T4), but extending a partial class is more standard c# development.
However I don't know the answer to 'is there a really good solution". Introducing a factory brings again new code to maintain, test and to understand, I am not sure this abstraction helps here because the factory itself would need to instantiate the dbcontext with the appropriate constructor (which you have to provide anyway).
Edit:
Just thought about it once more: the factory might be useful to resolve the connection string from another location (you said that you don't want the connectionstring in web.config), but that still doesn't solve the constructor problem

How to instantiate the repository that uses ninject in a unit test

I have a repository like:
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity
{
private readonly IContext _db;
public Repository(IContext context)
{
_db =context;
}
...
In Global.asax I have setup the ninject as:
kernel.Bind<IContext>().To<Context>();
This is working fine in the app probably because I'm explicity instantiating by calling the constructor with a paramater. There are problems in the unit tests however.
Then in a unit test I have:
var mockUnitOfWork = new Mock<UnitOfWork>();
var mockProjectApprovalRepository = new Mock<Repository<ProjectApproval>>();
mockUnitOfWork.Setup(x => x.ProjectApprovalRepository).Returns(mockProjectApprovalRepository.Object);
On this last line I get the error:
Can not instantiate proxy of class: MyNamespace.Repository Could not find a parameterless constructor.
I'm confused by this because I thought the point of Ninject was I didn't need to specify a parameterless constructor. Shouldn't ninject have instantiated a Context and used the constructor with one parameter.
When you do new Mock<Repository<ProjectApproval>>(), you're asking Moq to construct the object. If you asked Ninject to construct it, it would do it.
Ninject doesn't magically step in wherever construction happens - new is still new.
In this case, you can use an overload of the Mock constructor wherein you specify extra args.
Note that its generally accepted that Ninject shouldnt be anywhere near anything remotely close to the any common definition of the term Unit Test.

Does Ninject automatically inject non-bound classes?

public class MyController : Controller
{
private MyClass _class;
public MyController(MyClass class)
{
this._class = class;
}
}
public class MyClass
{
// stuff
}
My Ninject is hooked up to inject classes that implement IController (Controller class does so). But, I did not bind MyClass to anything, yet Ninject is still injecting MyClass into MyController.
I guess my question is, why does it inject something that I didn't bind to anything? Does Ninject run off an find the class with the signature MyClass? I assume this behavior would be different if my constructor required a MyBaseClass and I have two classes in my assembly that inherit from MyBaseClass?
In Ninject V1, ImplicitSelfBinding was a top-level config setting (which defaulted to true IIRC).
In V2, the implicit self binding behavior you observe is more deeply wired in (though there are ways of switching it off -- like most bits of Ninject, it's very granular and minimal). In V2, the default behavior is that self-bindings for concrete types are always generated if no other binding is present. The only time you typically do a Bind<Concrete>().ToSelf() is to customise the binding, e.g., to do a .InSingletonScope().
See this answer by #Remo Gloor for a way to turn it off in V2+.
Go do a grep in the source right now for ImplicitSelfBinding this instant - it's far easier to read than people rabbiting on though!
Also dont forget to have a look at Ninject.Extensions.Conventions and tests on ninject.org for arranging implicit Bind()ing of I*X* to *X*
(As Steven alluded to, Ninject would not self bind if you changed your MyClass class to be abstract.)

How to inject with Guice when there are two different constructors?

Total Guice noob here, have read a few articles and seen the intro video, that's about it.
Here's my simplified old code that I'm trying to "guicifiy". Can't quite figure out how to, since (as far as I understand), I can only #inject-annotate one of the two constructors? How can a calling class create the one or the other instance? Or will I have to refactor this somehow?
public class MyDialog extends JDialog {
public MyDialog( JFrame parent, <other parameters...> ) {
super( parent );
}
public MyDialog( JDialog parent, <other parameters...>) {
super( parent );
}
}
You can only inject into the one ctor.
Depending on how this class is being used, you could:
Inject a factory into the client code with two "new" methods.
Roll all the arguments into one ctor and pass null when not required.
How can a calling class create the one or the other instance?
This suggests that the calling classes will want multiple instances of MyDialog? Then you need to use a hand-rolled factory (Assisted Inject can handle this for you if you only had one ctor). I don't know the details of what you are up to and I'm likely repeating what you already know but as a blanked statement I'd suggest also extracting an interface from MyDialog and have the factory return them. This way you can fake MyDialog in tests.
Constructor injection is very clean. mlk is right, saying that you can inject into one constructor only.
What you can do is use method injection:
public class Smt {
private int a;
private Cereal cereal;
private Personality personality;
private ignition;
public Smt() {
this.a = 5;
}
public Smt(int a) {
this.a = a;
}
#Inject
public void setup(#CiniMini Cereal cereal, #Rastafarian Personality personality,
Ignition ignition) {
this.cereal = cereal;
this.personality = personality;
this.ignition = ignition;
}
}
What Guice will do is call your class' setup class method and provide all the injections. Then you do the same thing as in the constructor--assign the objects to your class' attributes.
I agree with the previous comments.
Just an additional hint: constructor injection is supposed to provide all dependencies a class needs. As mlk says, one approach could be to annotate the constructor with most arguments and then refactor the other one to call the former by passing null values where needed.
Additionally, Guice 3.0 supports the so called Constructor Bindings which allow the programmer to specify which constructor to use. See here for more details.

Resources