I want to resolve the dependency for the IEnumerable collections of the multiple class inheriting the Interface on the controller.
I want to resolve the following dependency during the application startup:
var notificationStrategy = new NotificationStrategy(
new INotificationService[]
{
new TextNotificationService(), // <-- inject any dependencies here
new EmailNotificationService() // <-- inject any dependencies here
});
NotificationStragey
public class NotificationStrategy : INotificatonStrategy
{
private readonly IEnumerable<INotificationService> notificationServices;
public NotificationStrategy(IEnumerable<INotificationService> notificationServices)
{
this.notificationServices = notificationServices ?? throw new ArgumentNullException(nameof(notificationServices));
}
}
What is the best way of dependency injection of IEnumerable types of objects in the asp.net core without using any external dependency or library?
Register all the types with the service collection at the composite root
//...
services.AddScoped<INotificationService, TextNotificationService>();
services.AddScoped<INotificationService, EmailNotificationService>();
services.AddScoped<INotificatonStrategy, NotificationStrategy>();
//...
and all dependencies should be injected when resolving the desired type since the constructor already has IEnumerable<INotificationService> as a constructor parameter
Reference Dependency injection in ASP.NET Core
Related
I have a controller's constructor in which I want to instantiate an object that gets access to the repository via dependency injection.
like this:
ContactController.cs: I get an error because I don't pass an IContactRepository
private ContactOperationsFacade contactOperator;
ContactController(){
contactOperator = new ContactOperationsFacade(//I want to use DI here);
}
ContactOperationsFacade.cs:
private readonly IContactRepository contactRepository;
public ContactOperationsFacade(IContactRepository contactRepositor){
this.contactRepository = contactRepository;
}
How can I instantiate this ContactOperationsFacade object in the controller's constructor still using DI for the repository?
In asp.net core you can do DI chaining as long as scopes allow it. So if A depends on B and the controller wants A you just add both A and B to the di container (ConfigureServices part of your code) and the container will figure it out.
Read more here https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1
ContactController should follow The Explicit Dependencies Principle
Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.
Also classes should depend on abstractions and not coupled to concretions.
So assuming something like
public class ContactOperationsFacade: IContactOperationsFacade { //<-Note interface/contract
private readonly IContactRepository contactRepository;
public ContactOperationsFacade(IContactRepository contactRepositor){
this.contactRepository = contactRepository;
}
//...
}
The controller should depend on the abstraction that the facade is derived from
public class ContactController: Controller {
private readonly IContactOperationsFacade contactOperator;
public ContactController(IContactOperationsFacade contactOperator){
this.contactOperator = contactOperator;
}
//...
}
And assumes that all the interfaces and implementations are registered with the DI container.
services.AddScoped<IContactOperationsFacade, ContactOperationsFacade>();
once all dependencies are registered the service provider should resolve them when activating the controller.
I want to register two dependencies using constructors with parameters but I want only to make 'new' on the 'Dependency' class one time.
Instead of this:
builder.RegisterInstance(new ClassA(new Dependency())).As<IClassA>().SingleInstance();
builder.RegisterInstance(new ClassB(new Dependency())).AsSelf().SingleInstance();
I want something like this:
Dependency dependency = new Dependency();
builder.RegisterInstance(new ClassA(dependency)).As<IClassA>().SingleInstance();
builder.RegisterInstance(new ClassB(dependency)).AsSelf().SingleInstance();
If you register the dependency first it should automatically get passed to the new instances if they require it.
Assumptions:
public class ClassA : IClassA
{
public ClassA(Dependency dependency)
{
}
}
public class ClassB
{
public ClassB(Dependency dependency)
{
}
}
Then register dependency
var dependency = new Dependency();
builder.RegisterInstance(dependency).As<Dependency>();
builder.RegisterType<ClassA>().As<IClassA>().SingleInstance();
builder.RegisterType<ClassB>().AsSelf().SingleInstance();
Assuming that there is a reason you want to instantiate the type instead of registering it with Autofac which will do it for you then you should use Register instead of RegisterInstance.
builder.RegisterType<Dependency>().As<Dependency>().SingleInstance();
builder.Register(t => new ClassA(t.Resolve<Dependency>())).As<IClassA>().SingleInstance();
You can then use the passed in IComponentContext to resolve any required dependencies. Do keep in mind that with SingleInstance your instance is only created once so dependencies should be scoped similarly (don't expect a per request dependency to "renew" itself with every call to your singleton).
I have a doubt since I'm new to Dependency Injection and IoC.
I have a domain layer (with business logic) and a data layer. We do not implement repositories, we use EF Core directly.
It is a Class Library project, we use it in a ASP.NET CCore Web API, WinForms, and inside another framework.
The idea is to use the same context inside a scope.
The problem is that I'm not being able to get the same context in the nested method execution, I'm sure it is because I did not understand the concept completely, can you guys give me a help on that?
Example:
public class MyTest
{
public void TestContainer()
{
var parentContext = MyContainer.Container.GetInstance<MyContext>();
TestParentAndChildContext(parentContext);
}
private void TestParentAndChildContext(MyContext parentContext)
{
var childContext = MyContainer.Container.GetInstance<MyContext>();
Assert.AreEqual(parentContext, childContext);
}
}
public class MyContainer
{
public static Container Container
{
get { return container ?? (container = RegisterAndVerifyContainer()); }
}
private static Container RegisterAndVerifyContainer()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new ExecutionContextScopeLifestyle();
container.Register<DbContext, MyContext>(Lifestyle.Scoped);
container.Verify();
return container;
}
}
In Simple Injector you register an implementation by its abstraction. In your case you registed an MyContext by its DbContext base type. From this point on Simple Injector will know that it will need to construct a MyContext in case someone asks for a DbContext. This is the whole purpose of
Program to an interface, not an implementation
In your case however, although you do register the MyContext by its abstraction, you request a new instance of MyContext directly, instead of requesting it through its abstraction. This causes Simple Injector to look for the MyContext in its list of registered abstractions. Since there is no registration for MyContext (there is for DbContext though, but that's a totally different type what Simple Injector is concerned), Simple Injector will try to add the missing registration. This succeeds because MyContext is concrete and has single resolvable constructor, while you are using Simple Injector v4.x.
By default the older versions of Simple Injector will resolve unregistered concrete types as Transient. This default changed in v5, where it won't create any unregistered concrete type by default.
So MyContext is resolved as transient when requested directly. You can solve this by changing your test to the following:
public void TestContainer()
{
using (MyContainer.Container.BeginExecutionContextScope()) {
var parentContext = MyContainer.Container.GetInstance<DbContext>();
TestParentAndChildContext(parentContext);
}
}
private void TestParentAndChildContext(MyContext parentContext)
{
var childContext = MyContainer.Container.GetInstance<DbContext>();
Assert.AreEqual(parentContext, childContext);
}
Do note that Simple Injector usually detects these kinds of mistakes. In case you register MyContext by its DbContext base type, but inject MyContext directly in a constructor of a type, Simple Injector will throw a Short-Circuited Dependency error when calling Verify().
The reason you didn't get warned about this, is because you've called Verify() before the resolve action (you should typically not call GetInstance from within your application; instead you should build all object graphs up front). But when you'd call Verify (again) after resolving MyContext you would see the exception popping up:
[TestMethod]
public void TestContainer()
{
var container = MyContainer.Container.GetInstance<DbContext>();
var parentContext = container.GetInstance<MyContext>();
var childContext = container.GetInstance<MyContext>();
// This call will fail
container.Verify();
}
When using ASP.NET MVC plus Entity Framework, and trying to implement a generic repository and a generic service, and have everything resolved by Unity Ioc:
I am trying to get Unity Ioc to inject a generic service into the controller using parameter injection, but the type resolving is failing with this this error message:
Activation error occured while trying to get instance of type
ISupplierService The current build operation (build key Build
Key[MyApp.Services.Implementation.SupplierService, null]) failed:
Activation error occured while trying to get instance of type
IGenericRepository1, key \"\" Resolution of the dependency failed:
The current type,
MyApp.Repository.Interfaces.IGenericRepository1[Entities.Supplier],
is an interface and cannot be constructed. Are you missing a type
mapping? (Strategy type BuildPlanStrategy, index 3)
I can understand that the error message means that it is trying to create an instance of IGenericRepository when instead I am actually trying to get it to create an instance of SupplierService, but I do not see why it is resolving this way. As per initial answers it could be because the types are not registered
The controller's service injection is:
public class SupplierController : Controller
{
private readonly ISupplierService _service;
public SupplierController() : this (null) { }
public SupplierController(ISupplierService service)
{
_service = service;
}
// .. injection fails, service is NULL
}
Supplier service is an empty interface plus empty class (which could have custom methods added later if needed)
public partial interface ISupplierService : IGenericService<Supplier> {}
IGenericService simply resurfaces the IGenericRepository's methods:
public interface IGenericService<T> : IDisposable where T : BaseEntity {}
In Global.asax.cs the IoC container is created by
var container = new UnityContainer();
var uri = new Uri(Assembly.GetExecutingAssembly().CodeBase);
string path = System.IO.Path.GetDirectoryName(uri.AbsolutePath);
var assemblyPaths = new List<string>
{
Path.Combine(path, "MyApp.Repository.Interfaces.dll"),
Path.Combine(path, "MyApp.Repository.Implementation.dll"),
Path.Combine(path, "MyApp.Services.Interfaces.dll"),
Path.Combine(path, "MyApp.Services.Implementation.dll")
};
container
.ConfigureAutoRegistration()
.LoadAssembliesFrom(assemblyPaths)
.ExcludeSystemAssemblies()
.Include(If.Any, Then.Register())
.ApplyAutoRegistration();
var serviceLocator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => serviceLocator);
experimented with UnityAutoRegistration while the latest release was still "fresh" and I was not happy with it. The TecX project on codeplex contains a port of the StructureMap config engine which gives you support for conventions that should make your life a lot easier.
Something like
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.Scan(s =>
{
s.AssembliesFromApplicationBaseDirectory();
s.With(new ImplementsIInterfaceNameConvention());
}
var container = new UnityContainer();
container.AddExtension(builder);
container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<>));
var serviceLocator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => serviceLocator);
should register all of your Interface/Service and Interface/Repository pairs. The convention registers SupplierService as the implementation of ISupplierService etc.
The additional call to RegisterType with the two open generic types (IGenericRepositoy<> and GenericRepository) maps your generic repository interface to the generic repository class. Unity will close the type definition automatically for you (i.e. IGenericRepository<Supplier> will be mapped to GenericRepository<Supplier>).
I'm using Munq as the DI container in a MVC3 project. I have a service layer that retrieves a DTO from a repository. Depending on a property in that DTO I need to use one of two strategies to perform calculations on the DTO. I can register a named type in the container e.g.
Container.Register<ICalculation>("Type1", c => new Type1Calculation);
Container.Register<ICalculation>("Type2", c => new Type2Calculation);
Then I can refer directly to the container when trying to instantiate the appropriate strategy e.g.
var calc = Container.Resolve<ICalculation>(dto.ServiceType);
But this leaves me with a dependency on the container itself with the associated coupling and testing issues. What do I need to pass into the service constructor that would allow me to get the correct calculation but without the dependency on the container? Should I pass in a factory instead so the dependency is in the factory and not in the service class?
Not sure about Munq, but Autofac allows you to pass around Funcs, so that you can skip all factories altogether:
public class Foo
{
public Foo(Func<string, IBar> barFactory) { }
}
Check if Munq allows for such behavior.
Otherwise -- yes, you'll have to resort to hand-written factories to provide yet another level of indirection.
I've added the Munq solution to this. First the factory which includes the IDependencyResolver interface to allow the factory to use the container to resolve dependencies in the factory method:
public class CalculationFactory
{
private readonly IDependencyResolver _resolver;
public CalculationFactory(IDependencyResolver resolver)
{
ThrowIfNullArgument(resolver, "resolver", typeof(IDependencyResolver));
_resolver = resolver;
}
public static ICalculation CreateCalculator(int serviceType)
{
switch (serviceType)
{
case 1: return _resolver.Resolve<ICalculation>("Type1");
case 2: return _resolver.Resolve<ICalculation>("Type2");
default: return _resolver.Resolve<ICalculation>("InvalidType");
}
}
}
Then in Global.asax.cs register the appropriate interfaces/classes, passing in the container to the factory. So now I can set up my tests and the only extra dependency is IDependencyResolver within the factory:
ioc.Register(c => new CalculationFactory(c));
ioc.Register<ICalculation>("Type1", c => c.Resolve<Type1Calculation>());
ioc.Register<ICalculation>("Type2", c => c.Resolve<Type2Calculation>());
ioc.Register<ICalculation>("InvalidType", c => c.Resolve<InvalidCalculation>());