É possível usar as notificações de um modo simples, apenas para atender um necessidade específica, criando apenas uma lista de mensagens, mas este padrão é poderoso o suficiente para que seja usado em domínios complexos, e combinado com outras abordagens. O projeto que desenvolvi tem um nível de complexidade médio, por este motivo já indiquei o Flunt, pois é uma forma de usar o conceito para validações com o mínimo de esforço e máxima confiabilidade, e assim já terá grandes ganhos, como a redução do uso de exceções e Ifs. Mas se você é como eu, que gostaria de usar ao máximo o padrão e ter controle sobre todo o seu funcionamento, vai ver como desenvolver e usar neste exemplo prático.
Quase todos os meus projetos são desenvolvidos usando a abordagem de arquitetura DDD, ou seja, quase sempre terá um projeto focado no domínio, assim como o uso de objetos de valor e pelo menos as camadas de domínio, aplicação e apresentação. Se você não faz ideia do que estou falando, não há problemas, é possível entender este artigo mesmo assim, mas se quiser saber mais sobre desenvolvimento dirigido ao domínio, segue a indicação de um excelente vídeo do Eduardo Pires, MVP da Microsoft.
Na pasta Domain inclua um projeto do tipo Class Library chamado DomainNotification.Domain, na pasta Application inclua um projeto do tipo Class Library chamado DomainNotification.Application e finalmente na pasta Presentation inclua um projeto do tipo Console application chamado DomainNotification.Prompt e defina como Set as StartUp project. A estrutura deve parecer como a imagem a seguir.
O projeto de domínio será onde residirão as entidades principais, assim como suas classes bases abstratas, também conhecidas como camada de Supertypes. Mas vamos começar criando as estruturas e classes de notificação, que estarão nesta camada.
No projeto de domínio, inclua uma pasta chamada Interfaces, e dentro desta pasta, outra chamada Notifications. Em Notifications, inclua uma interface chamada IDescription e INotification.
A interface INotification tem como objetivo definir um contrato para criação de notificações, definindo o mínimo que um classe precisa ter, ela facilita também o uso de injeção de dependência, podendo ajudar na redução de acoplamento entre projetos.
IDescription define um contrato mínimo para uma descrição de uma notificação lançada, assim como sobrescreve o método ToString() para que possa ser usada como um texto simples.
Ainda no projeto de domínio, inclua uma pasta chamada Notifications, e dentro desta pasta, inclua duas classes abstratas, uma chamada Description e outra chamada Notification.
A classe Description é abstrata, e tem como objetivo ser usada como herança para a classe que será a descrição da notificação em si, assim como a classe Notification que será usada como Supertype para a classe de notificação.
Estas quatro classes sustentam todo o core das notificações, fornecendo o mínimo para ser usado em uma entidade de domínio, por exemplo. mas também permite uma extensão do recurso, podendo adicionar outras peculiaridades necessárias.
Um dos principais usos de notificações é para tratamento de erros e validações de dados, e para isso, é economizado então uma parada e o lançamento desnecessário de uma exceção do Framework. A proposta aqui é criar um exemplo que usa uma interface e algumas classes básicas: ILevel, Error, ErrorDescription e classes para a severidade do erro.
A classe Error herda da classe abstrata Notification, mas estende a possibilidade de listar erros com descrição e nível, assim como verificar erros somente de um nível de severidade ou simplesmente checar se há erros de um tipo específico ou de modo geral.