Quero fazer algumas perguntas sobre as práticas recomendadas em relação aos tipos de mapeamento e ao uso de métodos de extensão em C #. Sei que esse tópico foi discutido várias vezes nos últimos anos, mas li muitos posts e ainda tenho dúvidas.
O problema que encontrei foi estender a classe que possuo com a funcionalidade "converter". Digamos que eu tenha a classe "Person" que representa um objeto que será usado por alguma lógica. Eu também tenho uma classe "Customer" que representa uma resposta da API externa (na verdade, haverá mais de uma API, portanto, preciso mapear a resposta de cada API para o tipo comum: Person). Eu tenho acesso ao código fonte de ambas as classes e, teoricamente, posso implementar meus próprios métodos lá. Preciso converter Customer em Person para salvá-lo no banco de dados. O projeto não usa nenhum mapeador automático.
Tenho 4 soluções possíveis em mente:
.ToPerson () na classe Consumer. É simples, mas parece que quebra o padrão de Responsabilidade Única para mim, especialmente porque a classe Consumer é mapeada para outras classes (algumas exigidas por outra API externa), portanto, seria necessário conter vários métodos de mapeamento.
Construtor de mapeamento na classe Person, tendo Consumer como argumento. Também é fácil e também parece quebrar o padrão de responsabilidade única. Eu precisaria ter vários construtores de mapeamento (já que haverá classe de outra API, fornecendo os mesmos dados que o Consumidor, mas em um formato ligeiramente diferente)
Classe de conversores com métodos de extensão. Dessa forma, eu posso escrever o método .ToPerson () para a classe Consumer e quando outra API é introduzida com sua própria classe NewConsumer, eu posso apenas escrever outro método de extensão e manter tudo no mesmo arquivo. Ouvi uma opinião de que os métodos de extensão são maus em geral e devem ser usados apenas se for absolutamente necessário, e é isso que está me impedindo. Caso contrário, eu gosto desta solução
Classe Conversor / Mapeador. Crio uma classe separada que manipulará conversões e implemente métodos que terão a instância da classe de origem como argumento e retornarão a instância da classe de destino.
Para resumir, meu problema pode ser reduzido a um número de perguntas (tudo no contexto do que descrevi acima):
Colocar o método de conversão dentro do objeto (POCO?) (Como o método .ToPerson () na classe Consumer) considera quebrar o padrão de responsabilidade única?
O uso de construtores de conversão na classe (semelhante ao DTO) é considerado uma quebra do padrão de responsabilidade única? Especialmente se essa classe puder ser convertida a partir de vários tipos de fontes, seriam necessários vários construtores de conversão?
O uso de métodos de extensão ao ter acesso ao código fonte da classe original é considerado uma má prática? Esse comportamento pode ser usado como padrão viável para separar a lógica ou é um anti-padrão?
Person
classe é um DTO? contém algum comportamento?