Lazy Dependency Injection for Microsoft DI ServiceProvider
Tags: dotnet, ioc, di, lazy
Published: 2021-01-30 04:53:03

Dependency Injection is a powerful tool and standard for achieving quality code. However, this can adversely affect performance and memory consumption, as instances may be created that are not used for the current request.

[The previous post](https://dev.to/hypercodeplace/lazy-dependency-injection-37en) detailed the problem and one solution that allows gracefully solving it without polluting your code. This solution is to use [LazyProxy](https://github.com/servicetitan/lazy-proxy) for IoC containers. The main idea is to substitute an object of the real type with a proxy. This proxy is a runtime generated type that implemented a specific interface `T` and called all members of this interface through `Lazy<T>`. Thus, the behavior changes as if `Lazy<T>` was injected instead of the `T` interface. Instances are created only on demand, but at the same time, the code remains clean.

Today I am happy to announce that `LazyProxy` became available for one more container. [LazyProxy.ServiceProvider](https://github.com/servicetitan/lazy-proxy-serviceprovider) library allows lazy dependency injection for [Microsoft's DI ServiceProvider](https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.serviceprovider?view=dotnet-plat-ext-5.0).

Usage of this library is similar to already existing libraries [LazyProxy.Unity](https://github.com/servicetitan/lazy-proxy-unity) and [LazyProxy.Autofac](https://github.com/servicetitan/lazy-proxy-autofac).

Here is an example of how to use this library. Consider the following interface and implementation:

```CSharp
public interface IFoo
{
    void Bar();
}

public class Foo: IFoo
{
    public Foo() => Console.WriteLine("Ctor");
    public void Bar() => Console.WriteLine("Bar");
}
```

A lazy registration for this service can be added like this:

```CSharp
// Creating a service collection
var services = new ServiceCollection();

// Adding a lazy registration
services.AddLazyScoped<IMyService, MyService>();

// Building the service provider
var serviceProvider = services.BuildServiceProvider()
```
Consider the following usage of the registered service:

```CSharp
Console.WriteLine("Resolving the service...");
var foo = serviceProvider.GetService<IFoo>();

Console.WriteLine("Executing the 'Bar' method...");
foo.Bar();
```

The output:

```
Resolving the service...
Executing the 'Bar' method...
Ctor
Bar
```

As you can see from the output, the constructor is not called until the first call to method `Bar` is made.

The initiative and brilliant initial implementation of the [LazyProxy.ServiceProvider](https://github.com/servicetitan/lazy-proxy-serviceprovider) library belong entirely to [Carlos Mendible](https://dev.to/cmendibl3), for which I want to express gratitude and appreciation on behalf of the entire open-source community. Besides, Carlos has generously permitted to move the new repository alongside all other LazyProxy's repositories. That was a big step forward in the lazy dependency injection ideas.

#GitHub Repositories
[LazyProxy](https://github.com/servicetitan/lazy-proxy)
[LazyProxy.Autofac](https://github.com/servicetitan/lazy-proxy-autofac)
[LazyProxy.Unity](https://github.com/servicetitan/lazy-proxy-unity)
[LazyProxy.ServiceProvider](https://github.com/servicetitan/lazy-proxy-serviceprovider)