Многоуровневый дизайн .net: возвращать код ошибки в формы, указывающий, какие элементы управления имеют ошибку - PullRequest
0 голосов
/ 10 марта 2011

Допустим, у меня есть простое приложение.Он пытается добавить новую запись в базу данных, получая информацию от пользователя.Информация представляет собой типичный объект MasterDetail, такой как счет-фактура.

  1. Объект Invoice, используемый для сбора данных, имеет несколько простых атрибутов (Id, Date и т. Д.) И список InvoiceDetail, состоящий изнекоторые простые атрибуты (invoiceId, productId, количество и т. д.)
  2. Форма на уровне пользовательского интерфейса собирает данные от пользователя, создает экземпляр Invoice и отправляет его на бизнес-уровень.Он имеет несколько простых элементов управления для простых атрибутов и DataGridView для списка InvoiceDetails.
  3. Бизнес-уровень отправляет данные в модуль проверки.Если во входных данных обнаружена какая-либо ошибка, она должна вернуть какой-либо код ошибки.
  4. Бизнес-уровень должен отправить код ошибки обратно в форму, чтобы позволить пользователю исправить неверную информацию.

Я хочу, чтобы приложение отображало какое-либо предупреждение (например, другой цвет фона) в каждом элементе управления формы с ошибкой.

  • Какой хороший подход для управления ошибками должен бытьв состоянии сообщить форме, какие элементы управления являются неправильными?
  • Могу ли я создать объект ошибки?
  • Использовать делегатов?

Более сложная проблема, которую я вижу, - найти конкретный элемент в деталях, поскольку этот список произвольно длинный, но даже без этой проблемы я понятия не имею, гденачало.

Я использую VB.net, но не думаю, что это имеет отношение к решению проблемы.PD: Пожалуйста, предложите мне несколько тегов к этому сообщению.

1 Ответ

1 голос
/ 10 марта 2011

Если об ошибке нужно уведомить пользователя (чтобы можно было исправить данные в форме), то лучший способ уведомить пользователя - использовать exception вместо использования загадочных кодов ошибок для обозначения ошибки.

Предположим, у вас есть метод в модуле Validation, который принимает экземпляр Invoice, тогда код в методе Validate() должен выглядеть примерно так:


Подход 1: перерыв при первом обнаружении исключения

public void Validate(Invoice invoiceInstance)
{
    foreach(InvoiceDetail invoiceDetail in invoiceInstance.InvoiceDetailsList)
    {
        if(invoiceDetail.quantity < 0)
        {
            throw new InvoiceDetailException("The invoice detail quantity is less than zero", InvoiceDetailExceptionType.Quantity, invoiceDetail);
        }

        // Validate other details
    }  
}

и в пользовательском интерфейсе catch the exception и его обработка,

try
{
    businessLayer.Validate();
}
catch(InvoiceDetailException invoiceDetailException)
{
    MessageBox.Show(invoiceDetailException.Message);
}

Пользовательский InvoiceException может быть создан следующим образом:

[Serializable]
public class InvoiceDetailException : Exception
{
    public InvoiceDetailExceptionType ExceptionType {get; private set;}

    public InvoiceDetail Detail {get; private set; }

    public InvoiceDetailException () { }

    public InvoiceDetailException (string message, InvoiceDetailExceptionType exType, InvoiceDetail detail) : base(message) 
    {
        this.ExceptionType = exType;
        this.Detail = detail;
    }

    public InvoiceDetailException (string message, Exception inner) : base(message, inner) { }

    protected InvoiceDetailException (
      System.Runtime.Serialization.SerializationInfo info,
      System.Runtime.Serialization.StreamingContext context)
        : base(info, context) { }
}

И перечисление InvoiceDetailExceptionType:

public enum InvoiceDetailExceptionType
{
    Quantity,
    ProductId
}


Подход 2: Показать совокупные исключения
Классы сущностей,

class Invoice
{
    public int Id { get; set; }
    public List<InvoiceDetail> Details { get; set; }

    public Invoice()
    {
        Details = new List<InvoiceDetail>();
    }
}

class InvoiceDetail
{
    public int InvoiceId
    { get; set; }

    public int Quantity
    { get; set; }

    public int ProductId
    { get; set; }
}


Валидатор

static class InvoiceValidator
{
    public static void Validate(Invoice invoice)
    {
        List detailsException = new List<InvoiceDetailException>();

        foreach (InvoiceDetail detail in invoice.Details)
        {
            try
            {
                ValidateDetail(detail);
            }
            catch (InvoiceDetailException detailException)
            {
                detailsException.Add(detailException);
            }
        }

        InvoiceException invoiceException = null;

        if (invoice.Id < 0)
        {
            // If error in the invoice field
             invoiceException = new InvoiceException("InvoiceId is invalid");
        }

        // Validate other fields of invoice...

        if (detailsException.Count > 0)
        {
            // If error in the details list
            if (invoiceException == null)
            {
                // If there is no error in the invoice field, then error only in details
                invoiceException = new InvoiceException("Exception only in details", detailsException);
            }
            else
            {
                // If there is error in invoice field as well as details
                invoiceException.DetailExceptionList = detailsException;
            }
        }

        if (invoiceException != null)
        {
            // If there is an error then throw exception
            throw invoiceException;
        }
    }

    private static void ValidateDetail(InvoiceDetail detail)
    {
        if (detail.Quantity <= 0)
        {
            throw new InvoiceDetailException("Quantity is invalid", InvoiceDetailExceptionType.Quantity, detail.InvoiceId, detail.ProductId);
        }

        // Validate other fields of invoice details...
    }
}


Пользовательские исключения,

[Serializable]
public class InvoiceDetailException : Exception
{
    public InvoiceDetailExceptionType DetailExceptionType { get; private set; }
    public int InvoiceId { get; private set; }
    public int ProductId { get; private set; }

    public InvoiceDetailException() { }

    public InvoiceDetailException(string message, InvoiceDetailExceptionType exceptionType, int invoiceId, int productId)
        : base(message)
    {
        this.DetailExceptionType = exceptionType;
        this.InvoiceId = invoiceId;
        this.ProductId = productId;
    }

    public InvoiceDetailException(string message, Exception inner) : base(message, inner) { }

    protected InvoiceDetailException(
    System.Runtime.Serialization.SerializationInfo info,
    System.Runtime.Serialization.StreamingContext context)
        : base(info, context) { }
}

[Serializable]
public class InvoiceException : Exception
{
    public List<InvoiceDetailException> DetailExceptionList { get; set; }
    public InvoiceException() { }

    public InvoiceException(string message): base(message) { }

    public InvoiceException(string message, List detailsExceptions) : base(message)
    {
        DetailExceptionList = detailsExceptions;
    }

    public InvoiceException(string message, Exception inner) : base(message, inner) { }

    protected InvoiceException(
      System.Runtime.Serialization.SerializationInfo info,
      System.Runtime.Serialization.StreamingContext context)
        : base(info, context) { }
}


Перечисление типа исключения,

public enum InvoiceDetailExceptionType
{
    Quantity,
    ProductId
}


И, наконец, вызов валидатора,

try
{
    InvoiceValidator.Validate(invoice);
}
catch (InvoiceException invoiceException)
{
    MessageBox.Show(invoiceException.Message);
    if (invoiceException.DetailExceptionList != null && invoiceException.DetailExceptionList.Count > 0)
    {
        Console.WriteLine("Exception in details :");
        foreach (InvoiceDetailException detailException in invoiceException.DetailExceptionList)
        {
            string printMessage = string.Format("{0}, InvoiceId = {1}, ProductId = {2}", detailException.Message, detailException.InvoiceId, detailException.ProductId);
            Console.WriteLine(printMessage);
        }
    }

    // If you want the caller to further handle the exception
    //throw;
}

Дополнительная информация

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...