How to use Dependency Injection in a class library? - c#

I have installed the Microsoft Dependency Injection into a .NET Framework 4.8 class library. I have also reigster interface A to class A. The problem is that my class B that takes a object of interface A in construtor still demands it when I try to create the class? So how do I get the DI system to provide this object in a class Library where there is no real entry point?
public Class B
{
B(){InterfaceA}
}
public Class A : InterfaceA
{}
public MainClass
{
public void DoStuff()
{
DependencyContainer.Register();
var myB = new B();
}
}
public DependencyContainer
{
public void Register()
{
(new ServiceCollection()).AddTransient<InterfaceA, A>();
}
}
Regards

DI means that any depencencies will come (get injected) from the outside. The class itself won't even know that dependency injection is used. In your case, the classes should be rewritten to accept dependencies instead of creating them:
public Class B
{
public A MyA {get;}
public B(InterfaceA a)
{
MyA=a;
}
}
public Class A : InterfaceA
{}
public MainClass
{
public B MyB {get;}
public MainClass(B b)
{
MyB=b;
}
public void DoStuff()
{
MyB......;
}
}
The classes know nothing about DI. When asked for a MainClass instance with, eg services.GetRequiredService<MyClass>(), the DI container will create all the necessary instances and pass them to the classes.
The common pattern for all .NET Core libraries is to provide extension methods that can be used to register or configure their classes in the main application's Startup class or ConfigureServices delegate. To do that, all that's needed is the IServicesCollection interface from the Microsoft.Extensions.DependencyInjection.Abstractions package. There's no need to add the full DI package :
public static class MyLibServiceExtensions
{
public static IServicesCollection AddMyClasses(this IServicesCollection services)
{
services.AddTransient<ClassB>()
.AddTransient<InterfaceA,ClassA>()
.AddTransient<MainClass>();
return services;
}
}
This can be used now to register the classes, eg in a Console application :
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddMyClasses()
.AddHostedService<Worker>();
});
}
Or the Startup.ConfigureServices method of a web app:
public class Startup
{
public Startup(IWebHostEnvironment env)
{
HostingEnvironment = env;
}
public IWebHostEnvironment HostingEnvironment { get; }
public void ConfigureServices(IServiceCollection services)
{
...
services.AddMyClasses();
}
}
The classes will now be injected into any class generated by the DI container, eg a `Controller:
public class MyController:ControllerBase
{
public MyController(MyDbContext dbContext,MainClass main)
{
_db=dbContext;
_main=main;
}
}

OK, so dependency injection isn't magic. Your Register method is building a collection of services and throwing it away. You need to actually resolve your components from the container (I'm not saying directly, but the container has to be involved).
You should build an IServiceProvider from it using the BuildServiceProvider method:
var serviceCollection = new ServiceCollection();
serviceCollection.AddTransient<InterfaceA, A>();
serviceCollection.AddTransient<B>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var b = serviceProvider.GetRequiredService<B>(); // constructs B and injects A
Probably you should do this in your Main method, and then inject B (or a Func to create B) into MainClass:
static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddTransient<MainClass>();
serviceCollection.AddTransient<InterfaceA, A>();
serviceCollection.AddTransient<B>();
serviceCollection.AddTransient<Func<B>>(provider => () => provider.GetRequiredService<B>()); // factory method
var serviceProvider = serviceCollection.BuildServiceProvider();
// ask the container for MainClass and then call DoStuff
var mainClass = serviceProvider.GetRequiredService<MainClass>();
mainClass.DoStuff();
}
And then you could rewrite MainClass like this:
public class MainClass
{
private readonly B _bInstance;
private readonly Func<B> _bFactory = new Func<B>();
// if you want to create instances of B as and when, I'd suggest using a factory
// otherwise you can pass in a single instance
// I've done both here as an example
public MainClass(Func<B> bFactory, B bInstance)
{
_bInstance = bInstance;
_bFactory = bFactory;
}
public void DoStuff()
{
// create two instances of B
var b1 = _bFactory();
var b2 = _bFactory();
}
}
While I advocate for using a factory when you need to build instances on the fly, it is possible to inject IServiceProvider itself into your classes, and then call its GetRequiredService or GetService methods. The reason I don't do this is because it is considered to be an anti-pattern. Using a factory allows you to still make changes at the composition root (i.e. in Main) without editing everywhere that creates instances of B.

Related

Having some parameters Injected with DI and some assigned manually

In a .NET Core 3.1 console application I want a Class that would have some parameters in constructor injected but some that I could assign manually. For example something like that but with IConfiguration Injected:
static void Main() {
var myObj1 = new MyClass(1);
var myObj2 = new MyClass(2);
}
public class MyClass {
public MyClass(IConfiguraiton config, int myVal)
{
}
}
I tried this with Ninject:
static void Main()
{
kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Get<MyClass>();
}
public class MyClass
{
public MyClass(IConfiguraiton config)
{
}
}
public class Bindings : NinjectModule
{
public override void Load()
{
var configuration = new ConfigurationBuilder().AddJsonFile($"appsettings.json").Build();
Bind<IConfiguration>().ToMethod(ctx => SetupConfiguration()).InSingletonScope();
Bind<MyClass>().ToSelf().InTransientScope();
}
}
I managed to make simple dependency injection, but haven't had any success making injection with parameters.
I've read a lot of people suggesting that it's better to pass parameters into methods of the class rather than constructor, however in my situation this isn't an option in addition I'm a software engineering student, and would like to learn how to do this, since it might be useful in some situations.
This is a situation where the Ninject.Extensions.Factory is useful, as it is made exactly for this situation. It does pull in the Factory dependency in addition to Castle.Core, as it uses DynamicProxy under the hood (as a SE student, playing with this library is a good idea for using the interceptor pattern).
To use it, you define a Factory interface like so:
public interface IMyClassFactory
{
MyClass Create(int myVal);
}
Note that the Create method returns MyClass, and the argument(s) to the Create method match exactly in type and name to the arguments you wish to provide. The argument type(s) you want injected must be registered with the kernel. Unfortunately, it is easy to make a mistake here - if you specify a parameter that does not exist in the factory interface it is ignored, but if you forget one it will throw an exception when called.
Next, register IMyClassFactory like this: Bind<IMyClassFactory>().ToFactory(); and remove your binding for MyClass. Then wherever you need to create an instance, inject IMyClassFactory and call Create: kernel.Get<IMyClassFactory>().Create(2)
You can achieve the same result without using Ninject.Extensions.Factory by writing and registering your own implementation of IMyClassFactory, essentially doing the same thing that the code the Factory extension ends up emitting. A full sample is below using both methods based on commenting in/out the registration (note the output if you add .InSingletonScope() to the registration of IConfiguraiton - both approaches respect the binding scopes of Ninject).
internal class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Bind<IConfiguraiton>().To<Configuraiton>();
kernel.Bind<IMyClassFactory>().ToFactory();
//kernel.Bind<IMyClassFactory>().To<NinjectMyClassFactory>().InSingletonScope();
var factory = kernel.Get<IMyClassFactory>();
var one = factory.Create(1);
var two = factory.Create(2);
}
}
public interface IMyClassFactory
{
MyClass Create(int myVal);
}
public class NinjectMyClassFactory : IMyClassFactory
{
public NinjectMyClassFactory(IResolutionRoot resolutionRoot)
{
ResolutionRoot = resolutionRoot;
}
private IResolutionRoot ResolutionRoot { get; }
public MyClass Create(int myVal)
{
return ResolutionRoot.Get<MyClass>(new ConstructorArgument("myVal", myVal));
}
}
public class MyClass
{
public MyClass(IConfiguraiton config, int myVal)
{
Console.Out.WriteLine("Created MyClass({0},{1})", config.MyNum, myVal);
}
}
public interface IConfiguraiton { int MyNum { get; } }
public class Configuraiton : IConfiguraiton
{
static int CreateCount;
public Configuraiton()
{
MyNum = Interlocked.Increment(ref CreateCount);
}
public int MyNum { get; }
}

Dependency Injection Into {get; set;} Property

I was wondering how I'd go about setting up my Dependency Injection to inject a dependency into properties that have public getters and setters ({get; set}).
So, an example would be:
namespace Dexter.Services {
public class CommandHandlerService : InitializableModule {
public CommandService CommandService { get; set; }
}
}
With the following dependency injector:
namespace Dexter {
public static class InitializeDependencies {
public static async Task Main() {
ServiceCollection ServiceCollection = new();
CommandService CommandService = new();
ServiceCollection.AddSingleton(CommandService);
Assembly.GetExecutingAssembly().GetTypes()
.Where(Type => Type.IsSubclassOf(typeof(InitializableModule)) && !Type.IsAbstract)
.ToList().ForEach(
Type => ServiceCollection.TryAddSingleton(Type)
);
ServiceProvider = ServiceCollection.BuildServiceProvider();
// Initialization stuff.
}
}
}
In this example, I would like the CommandService to automatically inject into the property.
I know this is possible because Discord.NET is able to do this, and I'd love to stick with that same codestyle.
( Discord.NET: https://docs.stillu.cc/guides/commands/dependency-injection.html )
Thanks! <3
This can be done without having to swap out the default DI container (IServiceProvider) using the Quickwire NuGet package.
Simply decorate your service with the [RegisterService] attribute and add [InjectService] to the property. No need for the interface.
[RegisterService(ServiceLifetime.Singleton)]
public class CommandHandlerService {
[InjectService]
public CommandService CommandService { get; set; }
}
Now from your main function, just call ScanCurrentAssembly:
public static async Task Main() {
ServiceCollection ServiceCollection = new();
ServiceCollection.ScanCurrentAssembly();
ServiceProvider = ServiceCollection.BuildServiceProvider();
// Initialization stuff.
}
Behind the scenes, ScanCurrentAssembly does all the necessary wiring to resolve dependencies, instantiate the class and inject it into properties.
For anyone curious, as per what Panagiotis recommended, a solution to this would be to create your own dependency injection. As such, I wrote a small method that loops through all the services in the provider, and attaches public properties to it. It may have bugs! Particularly regarding scoped services, of which I haven't written for it to support, but this should work as a good starting point for someone wishing to achieve a similar result!
public static object SetClassParameters(this object newClass, IServiceScope scope, IServiceProvider sp)
{
newClass.GetType().GetProperties().ToList().ForEach(property =>
{
if (property.PropertyType == typeof(IServiceProvider))
property.SetValue(newClass, sp);
else
{
object service = scope.ServiceProvider.GetService(property.PropertyType);
if (service != null)
{
property.SetValue(newClass, service);
}
}
});
return newClass;
}
Where you can use a method like the following to inject dependencies into classes. For instance, I wished to inject them into classes that extended an abstract "event" class that I made. This can be seen below:
using (var scope = serviceProvider.CreateScope()) {
GetEvents().ForEach(
type => serviceProvider.GetRequiredService(type).SetClassParameters(scope, serviceProvider)
);
}
Where GetEvents() is a reflexive function that returns all classes extending the abstract class given.

dependency injection or factory pattern c#

I have to write a Complex calculator logic which has 4 different components to be calculated brokerage, stockprice, admin charges & other charges. Each having a different logic and formulas.
So I decided to use Unity DI. I have a ContainerFactoryClass which resolves all classes which implements IChargeCalculator interface as shown below in the TotalAnnualCostCalculator constructor.
public class TotalAnnualCostCalculator
{
private readonly IUnityContainer container;
//Constructor
public TotalAnnualCostCalculator()
{
container = ContainerFactory.InitializeContainer();
ContainerFactory.SetupContainer(container);
}
public AnnualCostCharges CalculateTotalAnnualCost(Parameters product)
{
var calculators = container.ResolveAll<ICalculator>().ToList();
// Invoke calcualtion method
Parallel.ForEach(calculators, c =>
{
return c.CalculateAnnualCost(product);
});
}
}
Container Factory class:-
public static class ContainerFactory
{
public static IUnityContainer Container { get; private set; }
public static IUnityContainer InitializeContainer()
{
var container = new UnityContainer();
RegisterDependencies(container);
return container;
}
private static void RegisterDependencies(UnityContainer container)
{
container.RegisterType<ICalculatorStrategyFactory, CalculatorStrategyFactory>("Factory");
container.RegisterType<IEffectiveAnnualCostCalculator, InvestmentManagementChargeCalculator>("IMCChargeCalculator",
new InjectionConstructor(new ResolvedParameter<ICalculatorStrategyFactory>("Factory")));
//container.RegisterType<IEffectiveAnnualCostCalculator, AdministrationChargeCalculator>("AdministrationChargeCalculator");
container.RegisterType<IEffectiveAnnualCostCalculator, AdviceChargeCalculator>("AdviceChargeCalculator");
container.RegisterType<IEffectiveAnnualCostCalculator, OtherChargeCalculator>("OtherChargeCalculator");
container.RegisterType<IInvestmentManagementChargeCalculator, LumpSumIMCCalculator>("LumpSumIMCCalculator");
container.RegisterType<IInvestmentManagementChargeCalculator, DebitOrderIMCCalculator>("DebitOrderIMCCalculator");
}
public static void SetupContainer(IUnityContainer container)
{
Container = container;
}
}
Then any API consumes my Calculator.dll by just creating an instance of TotalAnnualCostCalculator and call a method like this.
var totalCharges = calc.CalculateTotalAnnualCost(prod);
My code reviewer says its better to use Factory Pattern ,as this tightly coupled to Unity Framework.
Please advise
Indeed, don't use a DI Container at all. As Steven suggests in the comments, this seems a great fit for a Composite:
public class TotalAnnualCostCalculator : ICalculator
{
private readonly ICalculator[] calculators;
public TotalAnnualCostCalculator(params ICalculator[] calculators)
{
this.calculators = calculators;
}
public AnnualCostCharges CalculateTotalAnnualCost(Parameters product)
{
Parallel.ForEach(this.calculators, c => c.CalculateAnnualCost(product));
}
}
In the Composition Root, then, you simply new up all the ICalculator objects you'd like to use, and pass them to the constructor of TotalAnnualCostCalculator.
Register all IEffectiveAnnualCostCalculator (or what ever interface).
You just need to map the enumerable to an array of the same type.
container.RegisterType<IEnumerable<IEffectiveAnnualCostCalculator>, IEffectiveAnnualCostCalculator[]>();
Resolve with dependency injection:
private IEnumerable<IEffectiveAnnualCostCalculator> calculators;
public TotalAnnualCostCalculator(IEnumerable<IEffectiveAnnualCostCalculator> calculators)
{
this.calculators = calculators;
}
public AnnualCostCharges CalculateTotalAnnualCost(Parameters product)
{
Parallel.ForEach(this.calculators, c => c.CalculateAnnualCost(product));
}

Dependency Injection Container - How to keep available to

When creating an application with Dependency Injection and it utilizes a framework for Dependency Injection such as Unity (or Ninject).
How do you initialize registering the interfaces to the container at the beginning all together and keep them available for the application to use throughout its running lifecycle of the application?
Do you need to pass the DI Container to each method that may utilize dependency injection, or is there some way to make the container globally accessible so that you can register them all together in the beginning and access them throughout running the application without having to continually pass them, and be able to utilize them when ever needed?
Environment: Visual Studio 2015, C#, Microsoft Unity (for DI Container)
Example Code
static void Main(string[] args)
{
// Make Unity resolve the interface, providing an instance
// of TrivialPursuit class
var diContainer = new UnityContainer();
diContainer.RegisterType<IGame, TrivialPursuit>();
var gameInstance = diContainer.Resolve<IGame>();
var xotherClass = new AnotherClass();
xotherClass.TestOtherClassOtherMethod();
}
------ Another class without context of the Dependency Injection Class ------
public void TestOtherClassOtherMethod()
{
IGame gameInstance = -- -Container is Not available to resolve from in this class ---
}
Reason: I don't want to need to pass every possible type that I may need later on to each class I load up, I will just want to use the instances when I need them. The more deeper I get into classes, later as the application becomes more complex, I won't want to pass down instances for each type up from the Main() method to each class.
A Dependency Injection (DI) container is just that. A framework for facilitating DI. You don't pass the container around in order to resolve instances of objects. You just request the type you need in your classes constructor and the DI framework will inject the appropriate dependency.
Mark Seemann has written a good book on dependency injection that I would recommend.
You register everything that'll need to be resolved with the container in the composition root. That is to say when your program starts up is when everything should be registered.
Let's say we have the following code:
public class MyClass
{
public Run()
{
var dependency = new Dependency1();
dependency.DoSomething();
}
}
public class Dependency1
{
public void DoSomething()
{
var dependency = new Dependency2();
dependeny.DoSomethingElse();
}
}
public class Dependency2
{
public void DoSomethingElse()
{
}
}
This gives us the above dependency chain: MyClass -> Dependency1 -> Dependency2.
The first thing we should do is refactor the classes to take their dependencies through their constructor and rely on interfaces rather than concretions. We can't inject dependencies unless there is a place to inject them (constructor, property, etc).
Here is the refactored code:
public interface IMyClass
{
void Run();
}
public interface IDependency1
{
void DoSomething();
}
public interface IDependency2
{
void DoSomethingElse();
}
public class MyClass : IMyClass
{
public readonly IDependency1 dep;
public MyClass(IDependency1 dep)
{
this.dep = dep;
}
public void Run()
{
this.dep.DoSomething();
}
}
public class Dependency1 : IDependency1
{
public readonly IDependency2 dep;
public MyClass(IDependency2 dep)
{
this.dep = dep;
}
public void DoSomething()
{
this.dep.DoSomethingElse();
}
}
public class Dependency2 : IDependency2
{
public void DoSomethingElse()
{
}
}
You'll notice the classes now all take their dependencies through their constructors and do not new up anything. Classes should only take in dependencies that they actually need. For example, MyClass does not NEED a Dependency2 so it doesn't ask for one. It only asks for a Dependency1 because that's all it needs. Dependency1 NEEDS Dependency2, not MyClass.
Now to wire it all up WITHOUT a container we would just new it all up in the composition root:
void Main()
{
var myClass = new MyClass(new Dependency1(new Dependency2()));
}
You can see how that could get cumbersom if we had tons of classes and depdencies. That's why we use a container. It handles all the depdency graph for us. With a container we'd rewrite it as follows:
void Main()
{
// the order of our registration does not matter.
var container = new Container();
container.Register<IDependency1>.For<Dependency1>();
container.Register<IDependency2>.For<Dependency2>();
container.Register<IMyClass>.For<MyClass>();
// then we request our first object like in the first example (MyClass);
var myClass = container.Resolve<IMyClass>();
myClass.Run();
}
In the second example the container will handle wiring up all the dependencies. So we never need to pass Depedency2 to MyClass and then to Depedency1. We only need to request it in Dependency1 and the container will wire it up for us like in the first example.
So in your example we would rewrite it like so:
static void Main(string[] args)
{
var game = new UnityContainer();
game.RegisterType<IGame, TrivialPursuit>();
game.RegisterType<IAnotherClass, AnotherClass>();
game.RegisterType<IYetAnotherClass, YetAnotherClass>();
var gameInstance = game.Resolve<IGame>();
// you'll need to perform some action on gameInstance now, like gameInstance.RunGame() or whatever.
}
public class Game : IGame
{
public Game(IAnotherClass anotherClass)
{
}
}
public class AnotherClass : IAnotherClass
{
public AnotherClass(IYetAnotherClass yetAnotherClass)
{
}
}
public class YetAnotherClass : IYetAnotherClass {}
In these cases there is no need to pass the container around. You register your dependencies with the container then request them in your classes constructors. If you wish to use the container in the class WITHOUT requesting it through the constructor then you are not doing DI you are just using the container as a singleton service locator. Something that should generally be avoided.
Container as a Service Locator
This should be generally avoided but if you want to use the container as a service locator you have two options:
1) Pass the container into your classes that need it through the constructor.
You can use the above examples for wiring your classes up for DI. But instead of requesting a dependency like IDependency in the constructor you just pass the container.
public class Game : IGame
{
public Game(IContainer container)
{
var blah = container.Resolve<IBlah>();
}
}
2) Request your container through a static class:
public static class ServiceLocator
{
private static IContainer container;
public static IContainer Container
{
get
{
if (container == null)
{
container = new Container();
}
return container;
}
}
}
Register everything as normal in your composition root using the ServiceLocator class. Then to use:
public class MyClass
{
public void DoSomething()
{
var blah = ServiceLocator.Container.Resolve<IBlah>();
}
}

Access or get Autofac Container inside a static class

I need to get or access to my IoC container in a static class. This is my (simplified) scenario:
I register dependencies for ASP .net Web Api in a Startup class (but also I do this for MVC or WCF. I have a DependecyResolver project, but for simplicity, consider the following code)
// Web Api project - Startup.cs
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
var builder = new ContainerBuilder();
// ... Omited for clarity
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.AsClosedTypesOf(typeof(IHandle<>))
.AsImplementedInterfaces();
// ...
IContainer container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// ...
}
Then, in a separate class library I have my static class (again simplified for clarity):
public static class DomainEvents
{
private static IContainer Container { get; set; }
static DomainEvents()
{
//Container = I need get my Autofac container here
}
public static void Register<T>(Action<T> callback) where T : IDomainEvent { /* ... */ }
public static void ClearCallbacks() { /* ... */ }
public static void Raise<T>(T args) where T : IDomainEvent
{
foreach (var handler in Container.Resolve<IEnumerable<IHandle<T>>>())
{
handler.Handle(args);
}
// ...
}
}
Any idea how can I get this?
I need to get or access to my IoC container in a static class.
Any idea how can I get this?
Yes, you don't! Seriously. The pattern with the static DomainEvents class originates from Udi Dahan, but even Udi has admitted that this was a bad design. Static classes that require dependencies of their own are extremely painful to work with. They make the system hard to test and maintain.
Instead, create a IDomainEvents abstraction and inject an implementation of that abstraction into classes that require publishing events. This completely solves the your problem.
You can define your DomainEvents class as follows:
public interface IDomainEvents
{
void Raise<T>(T args) where T : IDomainEvent;
}
// NOTE: DomainEvents depends on Autofac and should therefore be placed INSIDE
// your Composition Root.
private class AutofacDomainEvents : IDomainEvents
{
private readonly IComponentContext context;
public AutofacDomainEvents(IComponentContext context) {
if (context == null) throw new ArgumentNullException("context");
this.context = context;
}
public void Raise<T>(T args) where T : IDomainEvent {
var handlers = this.context.Resolve<IEnumerable<IHandle<T>>>();
foreach (var handler in handlers) {
handler.Handle(args);
}
}
}
And you can register this class as follows:
IContainer container = null;
var builder = new ContainerBuilder();
builder.RegisterType<AutofacDomainEvents>().As<IDomainEvent>()
.InstancePerLifetimeScope();
// Other registrations here
container = builder.Build();
You can create a static method inside your DomainEvents class to inject the container like this:
public static class DomainEvents
{
public static void SetContainer(IContainer container)
{
Container = container;
}
....
}
And then from your ASP.NET application, call this method to inject the container:
DomainEvents.SetContainer(container);
Please note that I am giving you a direct answer to your question. However, here are some issues that I see with this:
Static classes should not be used when the class requires dependencies. In such case, refactor to use a non-static class and use Constructor Injection to inject the dependencies that you need in the class.
Using the container outside of the Composition Root is called Service Location and is considered an anti-pattern.
Class libraries should not use the container or even have a Composition Root. Quoting from the Composition Root article that I referenced:
Only applications should have Composition Roots. Libraries and frameworks shouldn't.

Categories

Resources