How do I call an injected constructor without parameters? - c#

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
}
}

Related

How can I access a Class created with DI from a class not created with DI?

Preface - we have an old service that we need to upkeep and occasionally modify. Its architecture is not good, and it is a mammoth, but since we hope to deprecate it eventually my company does not want to currently fix its architecture.
Question:
I have a class MS. I need to change one of its methods so that instead of calling HTTP directly, it will do so via another existing class, AEO. AEO inherits from abstract class EC, has several fields it receives by means of DI, and is set up to be received by DI as well.
MS is not created via DI. Rather, the program.cs file that calls the method that adds DI, it creates a new instance of MS, manually passing its necessary parameters in.
How can I access AEO from within MS? If I just create new AEO(...) I will have an issue with passing the DI parameters which I do not have. If I just declare the Interface/Indexer as I would with normal DI, then upon creating new MS(...) I will have an issue of lacking the parameter to pass in to the constructor.
How can I make this work? Is it possible?
TIA
EDIT:
The way that AEO is declared with DI is thus:
builder.RegisterType<AEO>().Keyed<EC>(MCType.AEO)
.SingleInstance().WithAttributeFiltering();
answer edited 15-Dec-2022
Whenever I've had to perform this kind of refactoring in the past I've approached it from a different angle.
In order to mitigate risk the first step is to introduce your old service to the dependency injection process.
This will allow you to introduce replacement services, again using DI as you replace functionality.
Thus, you create an interface, IMS from MS, register that with your DI Container and then change your calling code to no longer work with a concrete instance of MS but IMS allowing the DI container to do its work.
Let us assume, for arguments sake that IMS is defined as:
interface IMS
{
public FunctionOne();
public HTTPFunction();
}
so that MS now implements that interface e.g.,
class MS : IMS
{
public FunctionOne()
{
//Do some work
}
public HTTPFunction()
{
//Make some HTTP calls
}
}
So you register MS interface (IMS) with DI container something like:
Container.Register<IMS, MS>("OldMS");
Thus you change in program.cs from
var msInstance = new MS();
to
var msInstance = Container.Resolve<IMS>("OldMS");
Testing should show that the program behaviour has not changed.
Next you wish to introduce AEO functionality for the one call in MS.
AEO inherits from abstract class EC, has several fields it receives by means of DI, and is set up to be received by DI as well.
You fail to mention whether AEO implements any additional methods or properties to those that it inherits from EC so I'll assume that it's registered with an interface IAEO e.g.,
Container.Register<IAEO, AEO>();
If not then please interpolate where necessary.
Next we create a wrapper class around MS functionality that implements the IMS interface e.g.,
class MSTwo : IMS
{
private IMS oldMs;
private IAEO aeo;
public MSTwo()
{
oldMS = Container.Resolve<IMS>("OldMS");
aeo = Container.Resolve<IAEO>();
}
public FunctionOne()
{
oldMS.FunctionOne();
}
public HTTPFunction()
{
aeo.SomeFunction();
}
}
This class you register with your DI Container e.g.,
Container.Register<IMS, MSTwo>("NewMS");
and it can then be resolved within program.cs
var msInstance = Container.Resolve<IMS>("NewMS");
Note: In the above examples, for simplicity, I've omitted any reference to DI through constructors, their registration with the DI Container nor there resolution at runtime as the syntax is often DI Container dependent.
Thanks to #Oliver Jacot-Descombes` comment, I found a working solution.
Before calling new MS(...) I used reflection to get an instance of AEO.
aeo = container.ResolveKeyed<EC>(MCType.AEO) as AEO;
and then passed aeo in to the new MS(...,aeo)

Where are concrete class injected in constructor being registered with DI framework?

I am trying to understand Dependency Injection where usually everything is injected as either via Constructor or Property Injection.
So far I have understood that it basically revolves around interface to mock the class.
I am checking out Nop Commerce where I came across CustomerModelFactory which accepts couple of Domain class like CustomerSettings,DatetimeSettings etc..
Now when I check the DependencyRegistrar.cs class, I don't see how the dependency registration or even in the same class, I don't see the new instance of CustomerSettings created anywhere.
So my question is when we inject concrete class in constructor of class, where do we register it or how IOC container supply the instance?
CustomerModelFactory.cs
public partial class CustomerModelFactory : ICustomerModelFactory
{
// all below are concrete class
public CustomerModelFactory(AddressSettings addressSettings,
CaptchaSettings captchaSettings,
CatalogSettings catalogSettings,
CommonSettings commonSettings,
CustomerSettings customerSettings,
DateTimeSettings dateTimeSettings,
}
DependencyRegistrar.cs
public class DependencyRegistrar : IDependencyRegistrar
{
public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)
{
builder.RegisterType<CustomerModelFactory>().As<ICustomerModelFactory>().InstancePerLifetimeScope();
}
}
I couldn't find where below is done:
CustomerSettings settings = new CustomerSettings();
or
CatalogSettings settings = new CatalogSettings();
How can I understand how this is working?
That's why DI does not really reduce complexity, instead, it hides complexity under surface and offload lifecycle management to another thing that you don't really know too much, as each DI framework is different. Anyway, that is another topic.
Here is to answer your question, ignore which DI framework, just think in general, there are 3 ways for you to get an instance of an object
Create the instance directly when you need it
CustomerSettings settings = new CustomerSettings();
Create the instance by Reflection when you need it
Type t = typeof(CustomerSettings);
CustomerSettings settings = Activator.CreateInstance(t) as CustomerSettings;
Cache all instances in a dictionary and look up when using the type name
something can be like this:
Dictionary<Type, object> lookup;
lookup.Add(typeof(CustomerSettings), new CustomerSettings()):
(This way does not generate a new instance though).
Now if you need the instance, you ask the dictionary to give it to you
lookup[typeof(CustomerSettings)]
This action, is called Resolved in many DI framework.
How does the DI framework find it though?
To do this, many DI framework will use reflection to find the matching type. There should always a process to register the types you want DI framework to resolve automatically. It means, you tell DI framework what type it needs to be aware, and then give it back to me when you look up using the type.
For example, you may see code like this:
container.Register<CustomerSettings>();
In this case, CustomerSettings is a class type, so DI knows how to create it when you need it.
However, if you are registering an interface
container.Register<ICustomerSettings, CustomerSettings>():
The above is one syntax to register interface and its concrete type. Basically, you tell DI, this is the type, and that is the implementation. So when you do this:
var setting = container.Resolve<ICustomerSettings>();
You will get an instance of CustomerSettings.
It will work if you have multiple implementations of the same interface, but you need some special handling. Different DI handles it differently.
Hopefully so far it makes a little sense.
Each DI framework has an IOC container, which acts like a dictionary. You register the type into there, and ask it to give it back.
There are more details, but I will not cover in here.
Concrete types are not automatically resolved by MS.DI; they need to be registered explicitly. NopCommerce, therefore, registers them inside its DependencyRegistrar class (on line 241):
//register all settings
var settings = typeFinder.FindClassesOfType(typeof(ISettings), false).ToList();
foreach (var setting in settings)
{
services.AddScoped(setting, serviceProvider =>
{
var storeId = DataSettingsManager.IsDatabaseInstalled()
? serviceProvider.GetRequiredService<IStoreContext>()
.GetCurrentStoreAsync().Result?.Id ?? 0
: 0;
return serviceProvider.GetRequiredService<ISettingService>()
.LoadSettingAsync(setting, storeId).Result;
});
}

Autofac Property Inject issues

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.

Ioc/DI - How to use the registered dependencies?

I think I'm missing a key part of how to actually use IoC/DI. I happen to be using the Unity container. I know how to setup a class to have it's dependencies injected and I also know how to make Unity register a type.
But what I don't know is how to actually then make use of these registrations.
So for example:
var container = new UnityContainer();
container.RegisterType<IRepository, XmlRepository>();
var service = new MyService(container.Resolve<IRepository>());
public interface IRepository
{
void GetStuff();
}
public class XmlRepository : IRepository
{
public void GetStuff()
{
throw new NotImplementedException();
}
}
public class MyService
{
private readonly IRepository _myRepository;
public MyService(IRepository repository)
{
_myRepository = repository;
}
}
Here I have a service layer which accepts a parameter of type IRepository. It's the container part that I seem to not be understanding.
Isn't the point of IoC/DI to be able to not have to manually resolve types every time I need to create an instance? In my code I'm getting the container to resolve a type, unless I'm misunderstanding how this is supposed to work, isn't the container supposed to somehow automatically (with reflection?) inject the dependency I told it to use when I registered the type? var service = new MyService(...) Is calling container.Resolve the correct way of doing this?
I've created a container, but how do I share this container amongst my project/code? This sort of relates to the first question. I had previously thought that there was a single place that you register types. So far the only way I can see how to get around this is to:
Keep registering types wherever I use them and end up with duplicated code
Pass the container around to every place I'm going to be resolving types
Neither of these ways are how I'd expect this to work
Isn't the point of IoC/DI to be able to not have to manually resolve types every time I need to create an instance?
No, that's the point of a DI Container, but there are drawbacks to using a container as well. Favour Pure DI over using a DI Container, as this will teach you how to use Dependency Injection using only first principles.
I've created a container, but how do I share this container amongst my project/code?
You don't. The DI Container should only be used in the Composition Root (if you use a DI Container at all).
Put your container setup in a module that runs when your program starts. You can call it from Main, for example. This is called a boot strapper.
See Dependency Injection with Unity for a good example of how to do this.
You don't need to do new MyService(container.Resolve<IRepository>()). To get an instance of MyService, just use container.Resolve<MyService>(); it will automatically resolves the dependencies for MyService.

Is this basically what an IOC like NInject does?

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.

Categories