Separando la capa de servicio de la capa de validación

Actualmente tengo una capa de servicio basada en el artículo.Validación con una capa de servicio. desde el sitio ASP.NET.

De acuerdo aesta Responda, este es un mal enfoque porque la lógica de servicio se mezcla con la lógica de validación que viola el principio de responsabilidad única.

Realmente me gusta la alternativa que se ofrece, pero durante la re-factorización de mi código me he encontrado con un problema que no puedo resolver.

Considere la siguiente interfaz de servicio:

interface IPurchaseOrderService
{
    void CreatePurchaseOrder(string partNumber, string supplierName);
}

Con la siguiente implementación concreta basada en la respuesta enlazada:

public class PurchaseOrderService : IPurchaseOrderService
{
    public void CreatePurchaseOrder(string partNumber, string supplierName)
    {
        var po = new PurchaseOrder
        {
            Part = PartsRepository.FirstOrDefault(p => p.Number == partNumber),
            Supplier = SupplierRepository.FirstOrDefault(p => p.Name == supplierName),
            // Other properties omitted for brevity...
        };

        validationProvider.Validate(po);
        purchaseOrderRepository.Add(po);
        unitOfWork.Savechanges();
    }
}

losPurchaseOrder El objeto que se pasa al validador también requiere otras dos entidades,Part ySupplier (Supongamos para este ejemplo que una orden de compra solo tiene una parte).

AmbosPart ySupplier los objetos podrían ser nulos si los detalles proporcionados por el usuario no corresponden a las entidades en la base de datos que requerirían que el validador arrojara una excepción.

El problema que tengo es que, en esta etapa, el validador ha perdido la información contextual (el número de pieza y el nombre del proveedor), por lo que no puede informar un error exacto al usuario. El mejor error que puedo proporcionar es en la línea de"Una orden de compra debe tener una parte asociada" lo que no tendría sentido para el usuario porque proporcionó un número de pieza (simplemente no existe en la base de datos).

Usando la clase de servicio del artículo de ASP.NET, estoy haciendo algo como esto:

public void CreatePurchaseOrder(string partNumber, string supplierName)
{
    var part = PartsRepository.FirstOrDefault(p => p.Number == partNumber);
    if (part == null)
    {
        validationDictionary.AddError("", 
            string.Format("Part number {0} does not exist.", partNumber);
    }

    var supplier = SupplierRepository.FirstOrDefault(p => p.Name == supplierName);
    if (supplier == null)
    {
        validationDictionary.AddError("",
            string.Format("Supplier named {0} does not exist.", supplierName);
    }

    var po = new PurchaseOrder
    {
        Part = part,
        Supplier = supplier,
    };

    purchaseOrderRepository.Add(po);
    unitOfWork.Savechanges();
}

Esto me permite proporcionar información de validación mucho mejor al usuario, pero significa que la lógica de validación está contenida directamente en la clase de servicio, violando el principio de responsabilidad única (el código también se duplica entre las clases de servicio).

¿Hay alguna manera de obtener lo mejor de ambos mundos? ¿Puedo separar la capa de servicio de la capa de validación y al mismo tiempo proporcionar el mismo nivel de información de error?

Respuestas a la pregunta(1)

Su respuesta a la pregunta