Есть ли способ использовать отражение или другой метод для динамического / динамического отображения объектов карты и взаимодействия с базой данных с соответствующими хранилищами? - PullRequest
0 голосов
/ 04 февраля 2020

У меня есть MyWizardDto, который я использую для перемещения объектов Dto между различными слоями. Объектами Dto может быть любое количество объектов. MyWizardDto используется в MyWizardAppService для вставки записей для каждого объекта в базу данных. В MyWizardAppService я заранее знал бы супер набор репозиториев, которые могут потребоваться, в настоящее время я добавил два для демонстрационных целей, но они могут увеличиться, и если какой-либо объект Dto равен нулю, нам не нужно отображать или вызывать его метод репозитория для взаимодействия с базой данных.

В методе MyWizardAppService.CreateOrUpdate я могу подключить несколько операторов if / else, чтобы сначала сопоставить каждый Dto (ClientDto, ContactDto) его соответствующей сущности (Client, Contact), используя Automapper, а затем вызвать соответствующий репозиторий (_clientRepository, _contactRepository) для добавления / обновления записи в базе данных. Однако мне интересно, могу ли я использовать рефлексию или какой-либо другой метод, чтобы избежать множественных операторов if / else, так как количество сущностей может увеличиться. Я всегда буду знать надмножество заранее, поэтому все соответствующие репозитории будут внедрены так же, как и текущие два репозитория.

Можно ли изменить мой MyWizardAppService.CreateOrUpdate метод для достижения sh моей цели без использования нескольких операторов if / else? Я придерживаюсь того же соглашения об именах, например, ClientDto, Client and _clientRepository, поэтому я не знаю, может ли это быть полезным для использования в качестве практического правила.

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;
        }

    }

В соответствии с предложением @Unknown, я изменил MyWizardAppService, как показано ниже, но теперь я получаю ошибку времени компиляции: Client / IRepository - это тип, который недопустим в данном контексте

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;
        }

    }

Обновление 2 Теперь я получаю сообщение об ошибке на TryGet, которое говорит Disctionary делает не содержит определения для 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;
        }

    }

1 Ответ

0 голосов
/ 04 февраля 2020

Не уверен, отвечает ли это на ваш вопрос. Если нет, просто примите это как подсказку.

Для удаления нескольких операторов if-else для отображения Dto на соответствующую модель вы можете сослаться на это post .

Для удаления несколько операторов if-else для вызова соответствующего репозитория, просто имейте Dictionary<Type,Repository> и предварительно инициализируйте его со всеми такими репозиториями.

//Just a sample code, not actual one.
repoDictionary.Add(<ClientModelType>,<ClientRepositoryInstance>);
repoDictionary.Add(<ContactModelType>,<ContactRepositoryInstance>);

Затем, вместо использования условных операторов, вы можете просто запросить репозиторий словарь для выполнения таких операций с БД.

//Just a sample code, not actual one.
Repository repo;
if(repoDictionary.TryGetValue(model.GetType(), out repo)){
  repo.CallRequiredMethod(model);
}

Надеюсь, это может вам как-то помочь.

...