Skip to content

Instantly share code, notes, and snippets.

@paulvanbladel
Last active October 17, 2022 13:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paulvanbladel/2c5b6481481de64ea1ac17086c2a3c6f to your computer and use it in GitHub Desktop.
Save paulvanbladel/2c5b6481481de64ea1ac17086c2a3c6f to your computer and use it in GitHub Desktop.
DI friendly factory pattern.
// this is how we want to consume the factory, here in the context of a razor page:
public class IndexModel : PageModel
{
private readonly IShapeRendererFactory _shapeRendererFactory;
public IndexModel( IShapeRendererFactory shapeRendererFactory)
{
_shapeRendererFactory = shapeRendererFactory;
}
public void OnGet()
{
var render = _shapeRendererFactory.Create<CircleRenderer>();
render.RenderMe();
}
}
// this is how we can make the DI registrations:
builder.Services.AddSingleton<OtherDep>();
builder.Services.AddSingleton<IShapeRenderer, CircleRenderer>();
builder.Services.AddSingleton<IShapeRenderer, TriangleRenderer>();
builder.Services.AddSingleton<IShapeRenderer, SquareRenderer>();
builder.Services.AddSingleton<IShapeRendererFactory>(ctx =>
{
var shapeRendererImplementations = ctx.GetServices<IShapeRenderer>();
var factories = new Dictionary<Type, Func<IShapeRenderer>>();
foreach (var item in shapeRendererImplementations)
{
factories.Add(item.GetType(), () => item);
}
return new ShapeRendererFactory(factories);
});
public interface IShapeRendererFactory
{
IShapeRenderer Create<T>() where T : class, IShapeRenderer;
}
public interface IShapeRenderer
{
public void RenderMe();
}
public class OtherDep { }
public class CircleRenderer : IShapeRenderer
{
private readonly OtherDep otherDep;
public CircleRenderer(OtherDep otherDep)
{
this.otherDep = otherDep;
}
public void RenderMe()
{
Console.WriteLine("I'm a circle");
}
}
public class TriangleRenderer : IShapeRenderer
{
public void RenderMe()
{
Console.WriteLine("I'm a triangle");
}
}
public class SquareRenderer : IShapeRenderer
{
public void RenderMe()
{
Console.WriteLine("I'm a square");
}
}
public class ShapeRendererFactory : IShapeRendererFactory
{
private readonly Dictionary<Type, Func<IShapeRenderer>> _factories;
public ShapeRendererFactory(Dictionary<Type, Func<IShapeRenderer>> factories)
{
_factories = factories;
}
public IShapeRenderer Create<T>() where T : class, IShapeRenderer
{
if (!_factories.TryGetValue(typeof(T), out var factory))
{
throw new ArgumentOutOfRangeException($"{typeof(T).Name} is not Registered");
}
return factory();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment