What is the preferred way to resolve a component at runtime? - c#

It is very possible to request some components after the root component has been resolved.
I understand we can use container.Resolve<ComponentInterface>() to get the component for this interface. However, it is neither recommended to reference the container everywhere, nor inject the container to the component. So where can we get this container?
I found something from the document of windsor that it is recommended to use the typed factory facility. However it looks we still need the container or the kernel:
var factory = kernel.Resolve<IDummyComponentFactory>();
var component = factory.GetSecondComponent();
Where should the kernel come from?
I even didn't see any benefit by using factory as it looks even more complex.
Thanks in advance!

Usually services could be injected into constructors and properties.
public class Component(IService service)
{
}
If something needs to be figured out at runtime, then typed factories become useful:
interface IService { }
interface IService<T> : IService { }
interface IServiceFactory
{
// This creates instance of IService<T>, where T is known at runtime
IService Create(Type type);
}
The implementation of typed factories usually have to use / have the DI container injected. However, that is an implementation detail decoupled from Component class. See Dependency Inversion Principle: https://deviq.com/dependency-inversion-principle/
The basic idea is your own types should, ideally, define a contract for dependent services , and only use the contract to instantiate IService<T>. Later if the implementation of the contract needs to be replaced with another, e.g. you decided to use new, or DI framework changed, your types will still work without needing to be modified.

Related

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

How to register two implementations then get one in .Net Core dependency injection

I have parts of my code which depend on more than one implementation of the same interface, and other parts which depend on one of the implementations.
I am registering implementations like:
services.AddSingleton<MyInterface, FirstImplementation>();
services.AddSingleton<MyInterface, SecondImplementation>();
Then getting both implementations when needed like:
var implementations= serviceProvider.GetServices<MyInterface>();
My Issue is when I need one of them, I am trying the following which returns null:
var firstImplementation= serviceProvider.GetService<FirstImplementation>();
Of course I could use:
var implementations= serviceProvider.GetServices<MyInterface>();
foreach (var implementation in implementations)
{
if (typeof(FirstImplementation) == implementation.GetType())
{
FirstImplementation firstImplementation = (FirstImplementation)implementation;
}
}
But I am thinking that I can get my FirstImplementation directly somehow.
The container knows how to resolve a FirstImplementation when asked for the MyInterface, how ever is was not told how to resolve a FirstImplementation when asked specifically for a FirstImplementation.
The built-in services container is meant to serve the basic needs of the framework and most consumer applications built on it. It is bare bones and needs to be configured explicitly to behave as desired. You will need to also tell it how to get the implementations when explicitly asked for the implementations
//register implementations first
services.AddSingleton<FirstImplementation>();
services.AddSingleton<SecondImplementation>();
//register interfaces using factory that return implementation singleton
services.AddSingleton<MyInterface, FirstImplementation>(p => p.GetService<FirstImplementation>());
services.AddSingleton<MyInterface, SecondImplementation>(p => p.GetService<SecondImplementation>());
So now you can get your FirstImplementation directly and get the same instance
var firstImplementation = serviceProvider.GetService<FirstImplementation>();
Actually what you did is not a good practice, You can create two different interfaces inherited from your base interface (MyInterface) and then register each implementation corresponding on the proper interface, After that in the part of your code which you need specific implementation you can ask from IoC go give you back specific implementation of your significant interface:
Implementation
public interface IFirstImplementation:MyInterface {}
public interface ISecondImplementation:MyInterface {}
Registeration
services.AddTransient<IFirstImplementation, FirstImplementation>();
services.AddTransient<ISecondImplementation, SecondImplementation>();
Usage
var firstImplementation= serviceProvider.GetService<IFirstImplementation>();
Microsoft.Extensions.Dependencyinjection provides the basic needs of Dependency injection, and there's other IoC container framework available for .NET which can solve your problem. For example, you can use Autofac's Named Services like below:
//registration method
var builder = new ContainerBuilder();
...
builder.RegisterType<FirstImplementation>().Named<MyInterface>("first");
builder.RegisterType<SecondImplementation>().Named<MyInterface>("second");
//resolve method
var firstImplementation = container.ResolveNamed<MyInterface>("first");
For more complicated scenario, you can use Keyed Services which supports resolving with an Index and attributes.
You also need to pay attention to the instance scope if uses Autofac.

Parameters of the TypedFactory are not bypassed further

There is a typed factory:
public interface IDataProviderFactory
{
IDataProvider Create(ConfigurationItem configurationItem);
void Release(IDataProvider dataProvider);
}
There are several implementations of IDataProvider
Some implementations are depend on ICalculator
There are several implementations of ICalculator
There is a configuration class:
public class ConfigurationItem
{
public CalculatorsEnum CalculatorsEnum { get; set; }
public DataPriversEnum DataPriversEnum { get; set; }
}
When I am trying to call the factory's method Create, Windsor is trying to resolve the IDataProvider's dependencies, which is ICalculator.
Here I need the container to use the information from the original parameter so that to understand which version of the ICalculator to use.
Update
I would like to add some details:
There is a class where I use IDataProviderFactory. There I control the lifecycle of the IDataProviders, I create and destroy them from time to time using the factory. So at this level I don't want to know anything about the IDataProvider implementation- there might be the DataProvider without a calculator.
At the beginning I had my own implementation of the IDataProviderFactory, where I could resolve ICalculator and inject it into the DataProvider. But when it comes to the recycling, I was disposing the DataProvider, but it appeared that disposing is not enough in case with Windsor when you manually resolve something, you need explicitly release it.
Possible solutions:
I still can do all this manually, but most likely I will break the beauty with some casting or so.
I can inject the typed factory of the Calculators into the DataProviders implementation, if needed, and control the lifecycle of the Calculator there. For example: I create the DataProvider with my factory and then I don't need it, I release it, the container will call the dispose of the DataProvider where I will release the Calculator with its own factory.
Windsor way?
Constructor parameters are only passed to the constructor of the top level service being resolved. This is by design.
The recommended solution would be to make a factory that resolves both ICalculator and IDataProvider. When resolving you would explicitly resolve ICalculator and then pass that into the factory function for IDataProvider.
See this question for further discussion.
Update
Yes every Resolve should have a matching Release, and this is true whether using factories or the container directly.
It would only be speculation to suggest what "the Windsor way" of addressing your particular scenario might be.
Windsor provides a number of different ways of specifying inline dependencies. See here for further details. Generally the methods outlined are preferable to using factories etc. because the resolving/releasing is managed by the container.

Ninject / IoC proper initialization of StandardKernel

I'm just getting started with IoC containers and have picked up Ninject to start with. I understand the principle of the separate modules you can incorporate into a Kernel. But I'm curious if I should have the first line below everywhere in my code where I'm about to ask for the concrete implementation of something from my service layer.
IKernel kernel = new StandardKernel(new SimpleModule());
// example: getting my ContentService
IContentService contentService = kernel.Get<IContentService>();
If I have a class with 10 methods that use the ContentService should I really new up a Module and a Kernel in every method? Seems like a code smell. How do most developers handle this with Ninject? Are there any articles online that show the proper way to do this with the consumer class?
If I have a class with 10 methods that use the ContentService should I
really new up a Module and a Kernel in every method?
No, you should have this class take IContentService as constructor parameter (since it depends on it inside its methods) and then ask the kernel to provide you the instance of this class. Your classes should know nothing about the DI container (Ninject in your case). They should never reference it.
There are, basically two ways of working with IoC: Dependency Injection (DI) and Service Location (SL).
When dealing with dependecy injection, you provide you dependencies from outside your classes. Generally, you do this by injecting (passing) your dependencies into the class constructor or by using setters. For example:
public class SomeClass {
public ISomeDependency SomeDependency {get;set;}
public SomeClass(ISomeOtherDependecy someOtherDependency) {
//...
}
}
In this case, you COULD provide a ISomeDependency implementation through the property and you SHOULD provide ISomeOtherDependecy implementation through the constructor. Ninject support both ways.
The other way of doing (SL) allows you to request for your dependencies in the moment you need, for example:
public void DoSomeAction() {
ISomeDependency someDependency = MyServiceLocatorImpl.GetInstance<ISomeDependence>()
}
If you plan to use the SL approach (or an hybrid one), you could use the Common Service Locator (Ninject has support for it) . It makes easy to switch our IoC engine later.

Interrupted chain of IoC

I am building an application which uses an Abstract Factory pattern to allow runtime determination of which subclass of my IHardwareDevice to create based upon how it responds to a request for identification. I might create Hardware1 or Hardware2.
The problem arises in that I want to use a State pattern in these IHardwareDevice objects and I want to have the State be created by the IoC container. Is there a good way to do this without directly calling the IoC container to resolve the State objects with which to hydrate the IHardwareDevice?
Or, am I thinking about this in the wrong way? Because my Factory is pretty much the entry point into this library, is it okay to have this Factory handle instantiating the container for use in the library? I was planning on having the client application instantiate the container and then use it to gain access to which ever parts of the library it requires, such as the Factory.
I am planning to use Windsor as the IoC container, but am at an early enough stage in the project to switch if needed.
Here's one way it can be done with Autofac 2.2 (http://autofac.org):
First, an enum to discriminate between states (making up some likely values):
public enum DeviceState { Online, Offline }
Then, the state implementations, like:
public class OnlineState : IDeviceState { }
Next, register each state with its corresponding enum key:
var builder = new ContainerBuilder();
builder.RegisterType<OnlineState>().Keyed<IDeviceState>(DeviceState.Online);
builder.RegisterType<OfflineState>().Keyed<IDeviceState>(DeviceState.Offline);
// Register other components here
Finally, the hardware device uses an index to choose states. The implementation of IIndex is provided automatically by the container:
public class Modem : IHardwareDevice
{
IIndex<DeviceState, IDeviceState> _states;
IDeviceState _currentState;
public Modem(IIndex<DeviceState, IDeviceState> states)
{
_states = states;
SwitchOn();
}
void SwitchOn()
{
_currentState = _states[DeviceState.Online];
}
}
Hope this helps.
Nick
Most IoC containers, including Windsor, has the option to pass explicit dependencies (parameters) to the constructors of the resolved dependencies; when you call the Resolve method.
So yes, you can pass your State object explicitly to the IHardwareDevice instance you are resolving.
Windsor has a very powerful facility for auto-implementing abstract factories - Typed Factory Facility
It is largely convention based, and if the default convention does not suit your needs, you can override it by providing custom ITypedFactoryComponentSelector.
It gives you access to all information you may need to make the decision - what inline arguments you want to pass down the invocation lane, and what component you want to resolve.

Categories