# Dependency Injected Blazor App

# Blazor Does Not Support Constructor Injection

Or does it?

## Code - gimme code

The v5.0.0-preview.8.20414.8 release included a nice refactor commit from [Mladen Macanović](https://github.com/stsrki) that introduced the  [IComponentActivator](https://github.com/dotnet/aspnetcore/blob/master/src/Components/Components/src/IComponentActivator.cs)  interface (along with a [default implementation](https://github.com/dotnet/aspnetcore/blob/master/src/Components/Components/src/DefaultComponentActivator.cs)).

It's a simple interface

```csharp
/// <summary>
/// Represents an activator that can be used to instantiate components.
/// The activator is not responsible for dependency injection, since the framework
/// performs dependency injection to the resulting instances separately.
/// </summary>
public interface IComponentActivator
{
    /// <summary>
    /// Creates a component of the specified type.
    /// </summary>
    /// <param name="componentType">The type of component to create.</param>
    /// <returns>A reference to the newly created component.</returns>
    IComponent CreateInstance(Type componentType);
}
``` 

The default implementation uses `Activator.CreateInstance` to create new components, which is the way the Blazor team designed it, and which is the reason you can't use constructor injection.

```csharp
public IComponent CreateInstance(Type componentType)
{
	var instance = Activator.CreateInstance(componentType);
	if (!(instance is IComponent component))
	{
		throw new ArgumentException($"The type {componentType.FullName} does not implement {nameof(IComponent)}.", nameof(componentType));
	}

	return component;
}
```

What if we - as a simple test - add some DI to that?
*Note: this is just an experiment - there are doubtless going to be better ways*

Create our own `IComponentActivator` and let DI inject an `IServiceProvider` so we can resolve Components.

```csharp
public class MyActivator : IComponentActivator
{
	public MyActivator(IServiceProvider serviceProvider)
	{
		ServiceProvider = serviceProvider;
	}

	IServiceProvider ServiceProvider { get; }
}
```
Now, lets change the method to get Components from the ServiceProvider:
```csharp
	public IComponent CreateInstance(Type componentType)
	{
		// Attempt to get a component from the ServiceProvider
		var spInstance = ServiceProvider.GetService(componentType);
		if (spInstance is IComponent spComponent)
		{
			return spComponent;
		}

		// Attempt to create it the original Blazor way
		var instance = Activator.CreateInstance(componentType);
		if (instance is IComponent component)
		{
			return component;
		}

		// That's not a known component!
		throw new ArgumentException($"The type {componentType.FullName} does not implement {nameof(IComponent)}.", nameof(componentType));
	}
```
Notice there is a fallback to the Activator.CreateInstance method of construction - in this case because I don't want to put all my Components into the DI container - it's just an experiment, not a torture device!

Also notice, in this *naive* implementation, there is no abstraction using interfaces - Blazor passes us an implementation type, so we can't ask DI for an interface implementation. That experiment would be for another time!

That also means we have to register the implemented component in DI, not using an interface.

```csharp
	public void ConfigureServices(IServiceCollection services)
	{
		// other services...
		services.AddScoped<IComponentActivator, MyActivator>();
		services.AddTransient<Counter2>();
	}
```
We register our custom activator and our component in DI.

Now, our component can do this
```csharp
	public partial class Counter2 
	{
		public Counter2(IJSRuntime jSRuntime)
		{
			JSRuntime = jSRuntime;
		}

		private IJSRuntime JSRuntime { get; }
		private int currentCount { get; set; }

		private async Task IncrementCount()
		{
			currentCount++;
			await JSRuntime.InvokeVoidAsync("alert", $"Counter: {currentCount}");
		}
	}
```
...and the required dependency `IJSRuntime` will be supplied by the DI system instead of using the `Inject` attribute/directive. 

## Summary

This was just an experiment to see where we are with constructor injection.
It is possible in a limited way.

