Reputation: 401
I am using an API which triggers the following method whenever data is accessible
public void Process(IData data)
IData
is implemented by several data types (i.e. EventData
and RegionData
) which all will trigger this method whenever new data is available.
This incoming data should be mapped to my entities through IDataMapper
:
IDataMapper<T,K> where T : IData where K : IEntity
My problem is how to resolve the corresponding DataMapper
based on the type of the the incoming data. My current solution is to make a manual check:
switch(data.GetType().Name) {
case nameof(EventData) :
var mapper = scope.ServiceProvider.GetRequiredService<IDataMapper<EventData, EventEntity>>();
break;
case nameof(RegionData) :
var mapper = scope.ServiceProvider.GetRequiredService<IDataMapper<RegionData, RegionEntity>>();
break;
.....
All data mappers are registered like this:
services.AddTransient<IDataMapper<EventData, EventEntity>, EventMapper>();
services.AddTransient<IDataMapper<RegionData, RegionEntity>, RegionMapper>();
Is it possible to make this more generic?
Upvotes: 1
Views: 62
Reputation: 5944
You could make the mapper generic too and move the problem of type checking inside that class. That way you can 'just' register one mapper type. This is also how Microsofts ILogger<TCategory>
works.
Example code:
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddTransient(typeof(IDataMapper<,>), typeof(DataMapper<,>));
serviceCollection.AddTransient<EventService>();
serviceCollection.AddTransient<RegionService>();
var provider = serviceCollection.BuildServiceProvider();
var eventService = provider.GetRequiredService<EventService>();
var regionService = provider.GetRequiredService<RegionService>();
}
}
class EventService
{
public EventService(IDataMapper<EventData, EventEntity> mapper)
{
mapper.Map(new EventData(), new EventEntity());
}
}
class RegionService
{
public RegionService(IDataMapper<RegionData, RegionEntity> mapper)
{
mapper.Map(new RegionData(), new RegionEntity());
}
}
public interface IData { }
public interface IEntity { }
public interface IDataMapper<T, K> where T : IData where K : IEntity
{
void Map(T data, K entity);
}
public class EventData : IData { }
public class RegionData : IData { }
public class EventEntity : IEntity { }
public class RegionEntity : IEntity { }
public class DataMapper<T, K> : IDataMapper<T, K> where T : IData where K : IEntity
{
public void Map(T data, K entity)
{
if (data is EventData eData && entity is EventEntity eEntity)
{
// map event
}
else if (data is RegionData rData && entity is RegionEntity rEntity)
{
// map region
}
}
}
}
Upvotes: 1