I have MyWizardDto
which I use to transfer Dto objects between different layers. The Dto objects can be any number of objects. MyWizardDto
is used in MyWizardAppService
to insert records for each entity into the database. In MyWizardAppService
I would know in advance the super set of repositories that may be required, currently I have added two for demonstration purposes but these can increase, and if any Dto object is null then we don't need to map or call its repository method for interacting with the database.
In MyWizardAppService.CreateOrUpdate
method, I can hardwire multiple if/else statements to first map each Dto (ClientDto, ContactDto)
to its corresponding entity (Client, Contact)
using Automapper
and then call the corresponding repository (_clientRepository, _contactRepository)
to add/update record into the database. However, I am wondering if I can use reflection or some other method to avoid multiple if/else statements as number of entities can increase. I will always know the superset in advance so all relevant repositories will be injected in the same way as the current two repositories.
Is it possible to change my MyWizardAppService.CreateOrUpdate
method to accomplish my objective without using multiple if/else statements? I am following the same naming convention e.g ClientDto, Client and _clientRepository
so I don't know if that can be of help for using as rule of thumb.
public class MyWizardDto
{
public ClientDto client { get; set; }
public ContactDto contact { get; set; }
}
public class ClientDto
{
public string Forename { get; set; }
public string Surname { get; set; }
public DateTime? DateOfBirth { get; set; }
}
public class ContactDto
{
public string Street { get; set; }
public string City{ get; set; }
}
public class Client
{
public string Forename { get; set; }
public string Surname { get; set; }
public DateTime? DateOfBirth { get; set; }
}
public class Contact
{
public string Street { get; set; }
public string City{ get; set; }
}
public interface IMyWizardAppService
{
Task<ResponseOutputDto> CreateOrUpdate(MyWizardDto myWizardDto);
}
public class ResponseOutputDto
{
public bool IsSuccess { get; set; }
public string Message { get; set; }
}
public class MyWizardAppService
{
private readonly IRepository<Client> _clientRepository;
private readonly IRepository<Contact> _contactRepository;
// there can be more repository entities
private ResponseOutputDto responseOutputDto;
public MyWizardAppService(
IRepository<Client> clientRepository,
IRepository<Contact> contactRepository)
{
_clientRepository = clientRepository;
_contactRepository = contactRepository;
responseOutputDto = new ResponseOutputDto();
}
public async Task<ResponseOutputDto> CreateOrUpdate(MyWizardDto myWizardDto)
{
PropertyInfo[] properties = myWizardDto.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
string temp = property.Name;
// to check if property is dto object and is not null
// if not null then map dto to its corresponding object e.g ClientDto to Client,
//I am using AutoMapper e.g ObjectMapper.Map<Client>(myWizardDto.client);
// now call corresponding entities repository e.g if ClientDto then call
// _clientRepository's insert.
}
//if no error return success
responseOutputDto.IsSuccess = true;
return responseOutputDto;
}
}
As suggested by @Unknown I changed the MyWizardAppService as shown below but now I get compile time error: Client / IRepository is a type which is not valid in the given context
public class MyWizardAppService
{
private readonly IRepository<Client> _clientRepository;
private readonly IRepository<Contact> _contactRepository;
private Dictionary<Type, IRepository> _repositoryPairs;
// there can be more repository entities
private ResponseOutputDto responseOutputDto;
public MyWizardAppService(
IRepository<Client> clientRepository,
IRepository<Contact> contactRepository)
{
_clientRepository = clientRepository;
_contactRepository = contactRepository;
responseOutputDto = new ResponseOutputDto();
_repositoryPairs = new Dictionary<Type, IRepository>();
//GET ERROR ON FOLLOWING LINE
_repositoryPairs.Add(<Client>, IRepository<Client>);
}
public async Task<ResponseOutputDto> CreateOrUpdate(MyWizardDto myWizardDto)
{
PropertyInfo[] properties = myWizardDto.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
string temp = property.Name;
// to check if property is dto object and is not null
// if not null then map dto to its corresponding object e.g ClientDto to Client,
//I am using AutoMapper e.g ObjectMapper.Map<Client>(myWizardDto.client);
// now call corresponding entities repository e.g if ClientDto then call
// _clientRepository's insert.
}
//if no error return success
responseOutputDto.IsSuccess = true;
return responseOutputDto;
}
}
Update 2 I now get error on TryGet it says Disctionary does not contain a definition for TryGet.
public class MyWizardAppService
{
private readonly IRepository<Client> _clientRepository;
private readonly IRepository<Contact> _contactRepository;
private Dictionary<Type, IRepository> _repositoryPairs;
// there can be more repository entities
private ResponseOutputDto responseOutputDto;
public MyWizardAppService(
IRepository<Client> clientRepository,
IRepository<Contact> contactRepository)
{
_clientRepository = clientRepository;
_contactRepository = contactRepository;
responseOutputDto = new ResponseOutputDto();
_repositoryPairs = new Dictionary<Type, IRepository>();
_repositoryPairs.Add(typeOf(Client), _clientRepository);
}
public async Task<ResponseOutputDto> CreateOrUpdate(MyWizardDto myWizardDto)
{
PropertyInfo[] properties = myWizardDto.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
string temp = property.Name;
IRepository repo;
if (_repositoryPairs.TryGet(property.GetType(), out repo))
{
//call insert here some how
}
// to check if property is dto object and is not null
// if not null then map dto to its corresponding object e.g ClientDto to Client,
//I am using AutoMapper e.g ObjectMapper.Map<Client>(myWizardDto.client);
// now call corresponding entities repository e.g if ClientDto then call
// _clientRepository's insert.
}
//if no error return success
responseOutputDto.IsSuccess = true;
return responseOutputDto;
}
}