Overriding components in Blazor

Eilev Hagen
.Net Programming
Published in
2 min readFeb 27, 2021
Photo by James Harrison on Unsplash

If you use a component library in your project, you might want to override a component somewhere deep down in the component hierarchy without having to override the whole hierarchy.

I spent some hours searching the web for a solution for this, without finding any up to date answers. With this article I hope to help others searching for the same.

By reading the Blazor source code on GitHub, I discovered that components are created through a DefaultComponentActivator, implementing the IComponentActivator interface. This means that we can create our own implementation of IComponentActivator that will replace the default one when we register it.

public class OverridableComponentActivator : IComponentActivator
{
private static Dictionary<Type, Type> _replaceTypes { get; set; }
= new Dictionary<Type, Type>();
public void RegisterOverride<TOriginal, TOverride>()
{
_replaceTypes.Add(typeof(TOriginal), typeof(TOverride));
}
public IComponent CreateInstance(Type componentType)
{
if (!typeof(IComponent).IsAssignableFrom(componentType))
{
throw new ArgumentException($"The type {componentType.FullName} does not implement {nameof(IComponent)}.", nameof(componentType));
}
if (_replaceTypes.ContainsKey(componentType))
{
componentType = _replaceTypes[componentType];
}
return (IComponent)Activator.CreateInstance(componentType)!;
}
}

By registering this in your Program.cs, you can now override any component:

var componentActivator = new OverridableComponentActivator();componentActivator.RegisterOverride<NavLink, MyNavLink>();builder.Services.AddSingleton<IComponentActivator>(componentActivator);

Be aware that the component signature should match the component that is overridden. If not, runtime errors can occur. This can be enforced by requiring inheritance:

public void RegisterOverride<TOriginal, TOverride>()
{
if (!typeof(TOriginal).IsAssignableFrom(typeof(TOverride)))
{
throw new ArgumentException($"{nameof(OverridableComponentActivator)}.{nameof(RegisterOverride)}: The override '{typeof(TOverride).FullName}' must implement '{typeof(TOriginal).FullName}'.");
}
_replaceTypes.Add(typeof(TOriginal), typeof(TOverride));
}

This is based on, and tested with, .NET5 Blazor webassembly.

Enjoy!

--

--