A lightweight implementation of the strategy pattern where the creation of instances is handled by the dependency injection framework.
Declare the strategy interface
public interface IShippingService
{
void Ship(string address);
}
Mark the different strategy implementations with the [Strategy("key")]
attribute with the associated key.
[Strategy("fedex")]
public class FedexShippingService : IShippingService
{
public void Ship(string address) => ...;
}
[Strategy("ups")]
public class UpsShippingService : IShippingService
{
public void Ship(string address) => ...;
}
Eventually add a default implementation to fallback to in case of no matches
[DefaultStrategy]
public class DefaultShippingService : IShippingService
{
public void Ship(string address) => ...;
}
After adding the strategy implementation to the IServiceCollection
register the strategy resolver
services
.AddScoped<IShippingService, FedexShippingService>()
.AddScoped<IShippingService, UpsShippingService>()
.AddScoped<IShippingService, DefaultShippingService>()
.AddStrategyResolver<IShippingService>();
In your code let the DI inject IStrategyResolver<T>
public OrderService(IStrategyResolver<IShippingService> resolver) =>
(_strategyResolver) = (resolver);
And use it to resolve the implementation matching the request key
foreach (var order in orders)
{
_strategyResolver
.Resolve(order.ShippingMethod)?
.Ship(order.Address);
}