I am using MVC with EF and Autofac. I have a concrete class called Helper. Helper is in another DLL and not the main MVC web application.
It has a property of type DBContext called 'Context'.
I want to inject an instance of the DBContext into this property - however its always null.
Here is what I have so far in GLobal:
var output = new DbContext(connectionString);
builder.RegisterInstance(output).As<DbContext>().PropertiesAutowired();
builder.RegisterType<Helper().WithParameter("Context",output).PropertiesAutowired();
// Set the dependency resolver to be Autofac.
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
Context is the property on the Helper class which I would like injected with the instance 'output'.
Context is always null.
In Autofac, the easiest way to manage dependencies is to leverage constructor injection.
Basically, instead of telling Autofac "wire up the properties for me and do your mojo", you tell him to let YOU in charge of declaring the list of components.
So, instead of wondering why property injection is not working, declare explicitly your dependencies in Helper constructor:
public class Helper
{
public DbContext Context { get; private set; }
public Helper(DbContext context /* Autofac is going to fill in this */)
{
Context = context;
}
}
Then, in Global (or in some other class encapsulating your registrations) you just tell Autofac to look at the Helper type and try his best to call the best constructor, which is the simplest thing you can do:
// Either InstancePerDependency, or SingleInstance, or something else depending upon you requirements.
builder.RegisterType<Helper>().AsSelf().InstancePerDependency();
And you should be done: Autofac will search for the constructor with most parameters (and there will be only one with a parameter of type DbContext and will check if he knows how to create parameters for the requested type (which he can).
So, voilà, you get a ready to use Helper!
Edit: I'm keeping the example above, because it's the correct answer to the question, BUT, to reply to the comment, I would use a little more machinery, in the form of an Init method:
public class Helper
{
public DbContext Context { get; private set; }
public Init(DbContext context /* Autofac is going to fill in this */)
{
Context = context;
}
}
And you can instruct Autofac to call this method during object initialization:
builder.RegisterType<CustomHelper>()
.AsSelf()
.InstancePerDependency()
.OnActivating(h => {
var dbContext = h.Context.Resolve<DbContext>();
((Helper)h.Instance).Init(dbContext);
});
OnActivating lets you write the explicit initialization call. Keep in mind you probably want to register all the types in an assembly which derive from Helper, but probably that is for another question.
Related
I have added the dependency injections to the project. But when i create an instance by using new keyword, dependency injection doesn't work.
public class MyClass
{
ILoginTokenKeyApi _loginTokenKeyApi;
public MyClass(ILoginTokenKeyApi loginTokenKeyApi)
{
_loginTokenKeyApi = loginTokenKeyApi;
}
...
}
When i try to create an instance of MyClass, it wants a parameter to be constructed naturally.
Just like this :
MyClass mc = new MyClass(); // ERROR, it wants a parameter (but it is what i want)
I have to do :
MyClass mc = new MyClass(new LoginTokenKeyClass()); // this is not a good code for me
How i create an instance of MyClass without parameter because it has dependency injected.
But when i create an instance by using new keyword, dependency injection doesn't work.
That’s fundamentally how dependency injection works.
With dependency injection, you are simply not supposed to new up new objects. That’s the whole point of dependency injection and inversion of control. Instead of creating objects and managing those objects’ dependencies, you are depending on the framework to give you the dependencies you need without having you to care about where they actually come from and how they are constructed properly. So you are moving the responsibility to create the object up to the caller.
If you find yourself in need to create an object that has a dependency, then this is a clear sign that you are doing it wrong. A common reason for this is that you want to create the object in order to manage its lifetime, or because it is actually a data object that just happens to have some operations that needs other dependencies to work (e.g. an entity that has a “save” method). In the first case, you simply don’t do it like that. You just depend on it and let the framework manage the lifetime; if it has an incorrect lifetime, then you should reconfigure it with the DI container.
In the latter case where you have a data object with operations, you should split this up. You should just have a data object, without any logic, and then inject some manager service that is able to perform the operation on that data object for you.
For example in ASP.NET Core Identity, you have the User object which is just a normal entity without any logic. In order to e.g. add user roles or change the password, you rely on the user manager which you can inject. So the User object itself is without any dependencies.
I’d generally suggest you to read the dependency injection chapter of the ASP.NET Core documentation to understand how dependency injection works and how it is supposed to be used within the framework.
As mentioned in the comments, it is not clear what you trying to achieve, but in order to do DI in .Net Core you have to create an interface IMyClass, then let your class implement that interface,
public interface IMyClass {
void SampleMethod();
}
public class MyClass : IMyClass
{
ILoginTokenKeyApi _loginTokenKeyApi;
public MyClass(ILoginTokenKeyApi loginTokenKeyApi)
{
_loginTokenKeyApi = loginTokenKeyApi;
}
public void SampleMethod()
{
// method logic goes here...
var xx = _loginTokenKeyApi.WhatEver;
}
}
then register ILoginTokenProvider and IMyClass in startup.cs
services.AddTransient<ILoginTokenProvider, LoginTokenProvider>();
services.AddTransient<IMyClass, MyClass>();
finally inject IMyClass where you need it:
public class IndexModel : PageModel {
private readonly IMyClass _myClass;
public IndexModel(IMyClass myClass)
{
_myClass = myClass;
}
public void OnGet()
{
_myClass.SampleMethod();
}
}
btw, it is also possible to register and inject MyClass without implementing IMyClass interface, but I prefer to follow basic programming principals :)
There are two types of Dependency Injections.
Constructor Injection - which you dont want
Property Injection - In this - you expose Public Get/Set property of the Object you want to be injected. And then in your DI config file (like spring.net) you can assign values.
Another way you can do DepInjection is that in the param less constructor - you can get the Object by a Key/Name. Like in Spring.Net we would do:
var UtilityObject = Spring.ContextRegistry.GetContext().GetObject("MyUtilObject") as TheUtilityClass;
I am writing a console app in .Net core. I want to use dependency injection. My architecture is like this. Program contains a TradeProcessor (which does all the work) which in turn makes some CompoundTrades. I have got DI passing some classes into the TradeProcessor via its constructor and that whole ServiceProvider setup. That works fine.
Now, if i want to DI some classes into the CompoundTrade does the TradeProcessor have to pass them in via the constructor? I was under the impression that if you register the class to be constructed, all the classes you want to pass in, then they all got passed in "under the hood". You call CompoundTrade () but the other constructor gets called. Am i confusing that with DI in Asp.Net? What is the best design pattern for doing this? Stick all the ServiceProviders in a static class?
You call CompoundTrade() but the other constructor gets called.
That's not how dependency injection works. If you call a constructor explicitly, you get exactly that constructor.
You will need to reference you container and tell your container to create an instance of that class for you.
If you have an instance that needs to dynamically create new objects that are registered in the container, you will need to pass in the container and then use that to create those new objects. Don't call a constructor directly.
public TradeProcessor(IServiceProvider provider)
{
// save the provider in a field
}
public void ThisNeedsADynamicallyCreatedContainerObject()
{
if(condition)
{
var instance = this.provider.GetService<ICompoundTrade>();
}
else
{
var instance = this.provider.GetService<ISingleTrade>();
}
}
Disclaimer: actual syntax may vary depending on the dependency injection provider you use.
I'm creating a Web API and I'm using dependency inject wit Ninject.
I have:
IRTWRepository
IModelFactory
I'm injecting those 2 into my controllers like this.
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IRTWRepository>().To<RTWRepository>();
kernel.Bind<RTWAPIContext>().To<RTWAPIContext>();
kernel.Bind<IModelFactory>().To<ModelFactory>();
}
My RTWRepository constructor looks like this
public class RTWRepository :IRTWRepository
{
private RTWAPIContext _context;
public RTWRepository(RTWAPIContext context)
{
_context = context;
}}
My ModelFactory constructor looks like this
public class ModelFactory : IModelFactory
{
private IRTWRepository _repo;
public ModelFactory(IRTWRepository repo)
{
_repo = repo;
}
}
I have a Controller that looks like this:
public MaterialsController(IRTWRepository repository,IModelFactory modelFactory)
: base(repository,modelFactory)
{
}
Now, my question is : Is Ninject creating 2 separate contexts when creating an instance of my RTWRepository and also when creating an instance of ModelFactory?.
The reason that I'm asking that is because I'm having a problem when I try to save an entity that has a dependency to another object which was previously retrieve from the db.
I'm saving the entity in my controller but I'm creating it in my model factory along with is dependency.
public class RecycleCenter
{
public RecycleCenter()
{
}
public int MyProperty { get; set; }
[Required]
public virtual Address Address { get; set; }
}
The code above is for the entity Recycle Center which has an Address, this recycle center entity is created in my model factory and then in my controller I try to save it but when my repository execute this line
_context.RecycleCenters.Add(entity);
I'm getting this error
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
So, somewhere in my code I'm using 2 context instead of 1 and I think is when creating the ModelFactory and RTWRepository, is this assumption correct?, if so how do I fix it?
TL;DR;
You probably need to change this line:
kernel.Bind<RTWAPIContext>().To<RTWAPIContext>();
to
kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InRequestContext();
Explanation:
When you define a binding in Ninject, you also specify how that object's lifecycle should be handled.
If you don't explicitly define it, Ninject's default lifecycle is Transient. Transient means that each time an instance is required, it will create a new one. In your case, you need to two instances: one for the RTWRepository of the ModelFactory and one for the RTWRepository of the MaterialsController.
You can modify the lifestyle to one of these options:
Singleton ==> kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InSingleTonScope();
Request ==> kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InRequestScope();
Thread ==> kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InThreadScope();
Named, Call, Parent, Custom
In your case, I think you need InRequestScope, but you have to check the necessary lifecycle as it depends on the application.
For further information please check out the documentation here: https://github.com/ninject/ninject/wiki/Object-Scopes
Most probably, it is. There's no annotation that is telling to Ninject "Hey, stop, when you have created the instance once, reuse it". You should agree that in most cases, you would want multiple instances of an object and that it is a rare case, where you want it only once.
If you want to reuse the instance, use the singleton pattern. Ninject is familiar with it, so you can bind the object mapping to a method
kernel.Bind<RTWAPIContext>().ToMethod(c => RTWAPIContext.GetInstance());
There is also a ToSingleton binding, but I bet you cannot make your context constructor private and implement C# specific singleton due to other ASP.NET problems (e.g. ASP.NET Identity will try to invoke the context's method for object creation).
I have the following constructor, where ISession is configured to resolve to an NHibernate session:
public EntityStore(ISession session)
{
Session = session;
}
The UnityConfig is as follows:
container.RegisterType<ISessionFactory>(new ContainerControlledLifetimeManager(), new InjectionFactory(sf => new NhibernateSessionFactory().GetSessionFactory()));
Now I would, for some reason, expect Unity to inject a session when I call the constructor as follows:
Claims = new EntityStore<TClaim, TKey>();
Could someone please help this absolute Unity novice on how to achieve what I describe above?
If you want your object to be created using Unity, you need to call one of Resolve methods. In your case you can do something like this:
Claims = container.Resolve<EntityStore<TClaim, TKey>>();
or
var s = container.Resolve<ISessionFactory>();
var Claims = new EntityStore<TClaim, TKey>(s);
There are two downsides to this approach. First, you you need to have access to container in your class, which is not always possible. Second, you are creating dependencies inside the class, which makes it to keep track of all dependencies.
Better approach would be to have all your dependencies injected as constructor parameters or properties, and use container.Resolve only in top level elements (e.g. Application class or main form). In this case you could replace your class so it injects EntityStore<TClaim, TKey> as constructor parameter:
public class YourClass
{
public YourClass(EntityStore<TClaim, TKey> store)
{
// save reference to store and use it later
}
}
Normally I would do this:
public class DBFactory
{
public UserDAO GetUserDao()
{
return new UserDao();
}
}
Where UserDao being the concrete implementation of IUserDao.
So now my code will be littered with:
DBFactory factory = new DBFactory();
IUserDao userDao = factory.GetUserDao();
User user = userDao.GetById(1);
Now if I wanted to swap implementaitons, I would have to go to my DBFactory and change my code to call a different implementation.
Now if I used NINject, I would bind the specific implementation on application startup, or via a config file. (or bind based on specific parameters etc. etc.).
Is that all there is too it? Or is there more?
(reason I am asking if I want to know how it will help me here: Help designing a order manager class)
In a word, yes. Your code would then change in structure, so your dependencies would be passed in via the constructor (or setters, which I am personally not a fan of). You would no longer say "new XXX()" for services in the body of your methods.
You also would not likely need the factory anymore at all, since the DI framework can act as a factory. You would likely just need a constructor dependency on IUserDAO.
So something like:
public class ClassThatNeedsUserDAO
{
private readonly IUserDAO _userDAO;
public ClassThatNeedsUserDAO(IUserDAO userDAO)
{
_userDAO = userDAO;
}
public User MyMethod(userId)
{
return _userDAO.GetById(int userId);
}
}
There is more to it, one example would be if the constructor of UserDao required some other objects to be passed as arguments (dependencies).
You could have ninject automatically create and inject those objects, saving some lines of code but more importantly ensuring that every class is loosely coupled with its dependencies.