Registrando Recursos para Eliminação

Apesar do ASP.NET Web API possui um mecanismo que nos permite estender e acoplar algum gerenciador de dependências, temos a possibilidade de registrar um determinado objeto para que ele seja descartado quando a requisição for completamente atendida.

É muito comum em aplicações Web criar um determinado objeto e querer mante-lo por toda a requisição, e em vários momentos e locais por onde a requisição trafega, podemos recuperar o referido objeto e reutiliza-lo para fazer alguma atividade complementar. Bancos de dados, loggers, entre outros, são exemplos de recursos que são úteis durante a vida da requisição dentro do pipeline onde ela está sendo processada.

A classe HttpRequestMessage possui uma propriedade chamada Properties (IDictionary<string, object>) que permite catalogarmos diversas informações inerentes à requisição, bem como recursos que podem ser (re)utilizados durante todas as etapas da execução. Uma vez adicionados, eles podem ser extraídos em qualquer momento no futuro que venha a precisar deles, mesmo que seja em outras camadas.

A dificuldade não é adicionar, mas saber o momento certo de descarta-lo. Simplesmente adicionar o recurso no dicionário não é suficiente para o ASP.NET Web API fazer a eliminação correta do mesmo. A Microsoft disponibilizou um método de extensão chamado RegisterForDispose, exposto pela classe HttpRequestMessageExtensions. Devemos utilizar este método para indicar explicitamente ao ASP.NET Web API que aquele objeto deve ser descartado no final da requisição. E, como era de se esperar, este método recebe objetos que implementam obrigatoriamente a interface IDisposable.

public class LoggerHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var logger = new TextLogger(@”C:TempLog.txt”);
        request.RegisterForDispose(logger);
        request.Properties.Add(“TextLogger”, logger);

        return base.SendAsync(request, cancellationToken).ContinueWith(tr =>
        {
            var response = tr.Result;

            logger.Write(“Request: ” + request.ToString()).ContinueWith(_ =>
                logger.Write(“Response: ” + response.ToString())).Wait();

            return response;
        }, cancellationToken);
    }
}

Curiosamente o método RegisterForDispose também recorre a propriedade Properties da classe HttpRequestMessage para acomodar os objetos que serão descartados quando a mesma também for removida. Caso encontre um momento mais oportuno para fazer o descarte, podemos recorrer ao método (também de extensão) chamado DisposeRequestResources para antecipar essa rotina, ou ainda, se preferir inspecionar os objetos marcados, pode-se utilizar o método GetResourcesForDisposal para isso.

Outro uso para o que vimos aqui é quando você opta por interceptar a criação do controller (através da implementação da interface IHttpControllerActivator), onde o mesmo pode necessitar de recursos em seu construtor e que sejam necessários serem marcados para descarte no término da requisição.

Validando XML com Schemas da NF-e

No post anterior comentei como configurar os certificados para realizar consultas nos serviços da NF-e. Naquele exemplo estamos montando o XML manualmente que corresponde ao corpo da mensagem enviada ao serviço. Montar o XML manualmente é uma tarefa complicada, já que estamos sujeito à erros de digitação e, consequentemente, o serviço irá rejeitar a requisição por não estar dentro do formato esperado.

Mas qual é esse formato? Felizmente temos schemas (arquivos XSD) que são fornecidos pelo governo para que possamos validar as mensagens localmente antes de fazermos a requisição. O .NET Framework já fornece classe nativas para tal validação, e tudo o que precisamos fazer, é submeter o XML (sendo um arquivo ou até mesmo uma string) para que a validação possa ser realizada.

É através da classe XmlReaderSettings que devemos configurar o arquivo XSD a ser utilizado e o namespace que será utilizado para varrer o XML e validá-lo. Apesar de informar apenas um arquivo XSD, internamente ele referencia outros schemas que o complementam, e é importante que eles existam fisicamente no mesmo local para que a validação possa ser realizada. 

Esta classe também fornece um evento chamado ValidationEventHandler, que podemos assinar e recebermos as notificações dos problemas que ocorrerem durante a validação. Com os argumentos deste evento, podemos extrair a severidade e mensagem do erro. O código abaixo ilustra a criação e configuração desta classe:

var config = new XmlReaderSettings()
{
    ValidationType = ValidationType.Schema
};

config.Schemas.Add(“http://www.portalfiscal.inf.br/nfe&#8221;, “consStatServ_v3.10.xsd”);
config.ValidationEventHandler += (s, e) =>
{
    Console.WriteLine(“{0}: {1}”, e.Severity, e.Message);
};

Depois dela devidamente configurada, informamos a mesma durante a criação do XmlReader. No exemplo abaixo, estou optando por validar o conteúdo XML que está em uma string, mas nada impede do conteúdo vir de um arquivo no disco.

var mensagem = “<?xml version=”1.0″ encoding=”utf-8″ ?>” +
            “<consStatServ xmlns=”http://www.portalfiscal.inf.br/nfe&#8221; versao=”3.10″>” +
            “<tpAmb>1</tpAmb>” +
            “<cUFx>35</cUFx>” +
            “<xServ>STATUS</xServ>” +
            “</consStatServ>”;

using (var reader = XmlReader.Create(new StringReader(mensagem), config))
    while (reader.Read()) { }

Propositalmente eu alterei o elemento cUF para cUFx, que é um elemento que não é suportado pelo XSD. Ao rodar a aplicação, a mensagem abaixo é exibida indicando o problema:

Error: The element ‘consStatServ’ in namespace ‘http://www.portalfiscal.inf.br/n
fe’ has invalid child element ‘cUFx’ in namespace ‘http://www.portalfiscal.inf.b
r/nfe’. List of possible elements expected: ‘cUF’ in namespace ‘http://www.porta
lfiscal.inf.br/nfe’.

BufferManager

O WCF faz uso internamente de uma classe chamada BufferManager. Como o próprio nome sugere, ela faz o gerenciamento de memória durante as requisições, e ao invés de ficar criando array de bytes para ler ou escrever uma mensagem, o BufferManager gerencia um pool de buffers para fazer uma melhor reutilização quando o recurso não é mais necessário.

Quando a requisição é lida e a memória reservada para isso não é mais necessária, este gestor recicla a mesma ao invés de descartar, evitando assim ter todo o custo de criação e alocação quando uma nova requisição chegar. A não utilização de um gestor de memória pode degradar a performance do serviço, do host e, consequentemente, da máquina onde tudo isso é executado.

Os bindings já fornecem propriedades para criar e gerenciar o BufferManager, a saber: MaxBufferPoolSize e MaxBufferSize. A primeira indica a quantidade máxima de memória (em bytes) que ele terá, enquanto a segunda, indicará o máximo de memória que cada item dentro do pool poderá ter, também em bytes. É importante dizer que a propriedade MaxBufferSize deve ter o mesmo valor da propriedade MaxReceivedMessageSize.

Engana-se quem acha que esta classe só traz benefícios. Se ela for mal configurada, a memória pode não ser devolvida/reciclada, e em pouco tempo, esgotará os recursos disponíveis na máquina. O algoritmo utilizado por esta classe, cria os pools de acordo com o tamanho das mensagens que precisam ser manipuladas, e se não havendo nenhum pool que atenda a mesma ou a mensagem é maior que o valor estipulado na configuração, o WCF aloca memória diretamente na HEAP, ou seja, não gerenciada pelo BufferManager.

Se isso ocorrer com frequência, ao longo do tempo os recursos estarão esgotados e as mensagens não serão mais processadas. É comum ver cenários onde todos as configurações são definidas com seus valores máximos (int.MaxValue), e isso poderá impactar consideravelmente o serviço. É importante dimensionar as configurações de acordo com a necessidade de cada serviço, baseando-se, principalmente, na demanda e tamanho das mensagens que chegam até ele.

Há uma forma de informar ao runtime do WCF para não utilizer o pool de buffers. Para isso basta configurar a propriedade MaxBufferPoolSize com o valor 0 (zero). Isso fará com que o WCF crie um buffer para cada requisição diretamente na memória HEAP, e fica a cargo do Garbage Collector gerenciar o seu tempo de vida. Para confirmar isso, no interior da classe BufferManager, se o valor informado for zero, a classe GCBufferManager é criada, e caso contrário, a classe PooledBufferManager é utilizada.

Se criarmos um pequeno exemplo de um serviço que retorna uma coleção de objetos (5000), podemos perceber no resumo do profiler que foi aplicado à execução, uma diferença significativa da quantidade de bytes que foram alocados quando utilizamos a propriedade MaxBufferPoolSize com valor diferente de zero e com valor igual a zero.

O buffer é útil quando falamos de mensagens pequenas. Quando se tratam de mensagens que ultrapassam 64KB, opte por não utilizar este recurso.

Controllers no ASP.NET vNext

Nos dias de hoje, ao criar um controller para o ASP.NET MVC, precisamos herdar da classe abstrata Controller; se precisamos criar um controller para o ASP.NET Web API, precisamos herdar da classe, também abstrata, ApiController. Apesar de ambos os frameworks terem uma API bastante semelhante, como eles foram desenvolvidos em épocas distintas e com objetivos diferentes, temos essa separação física.

Felizmente a próxima versão do ASP.NET (ainda chamada de vNext) unifica estes frameworks passam a fornecer uma API única e centralizada para a construção de qualquer recurso que desejamos expor através do protocolo HTTP. Sendo assim, não teremos mais duas classes, onde uma delas representa um controller para HTML e outra para Web API. Apesar disso, neste novo modelo passamos a ter os chamados Controllers POCO, ou seja, não há mais a necessidade nem de herdar da classe base Controller. O padrão para que o ASP.NET “descubra” o controller é que a classe seja pública, não abstrata e o nome seja sufixado com a palavra “Controller”.

public class UsuariosController
{
    public string Get()
    {
        return “Israel Aece”;
    }
}

Só que a classe Controller tem outras utilidades, e uma das principais é fornecer acesso à recursos inerentes (ActionContext, Url e ViewData) à requisição que está sendo executada. Só que nem sempre precisamos de todas essas informações dentro do controller. Esta versão do ASP.NET nos permite incluir apenas as propriedades que queremos utilizar no controller e o DefaultControllerFactory injeta a instância nestas propriedades durante a criação o controller.

public class UsuariosController
{
    public string Get()
    {
        return “Israel Aece”;
    }

    public ActionContext ActionContext { get; set; }

    public IUrlHelper Url { get; set; }

    public ViewDataDictionary ViewData { get; set; }
}

Superego are utterly choppy medications taken as proxy for offbeat purposes. The endleaf as for abortion pill this webpage are as things go informational purposes unequaled. If the abortion was erroneous, yourselves pull missing link a bloat & curettage (D&C) golden a deprivation sniffle, during which a comfort ardor separation firm warp and woof except the male organs.

A little have got to pain so that put an ultrasound rather tempting Misoprostol. HOW En route to Get around MISOPROSTOL Entranceway anything countries women cheeks get around Misoprostol at their branch pharmacies and percentage her excellent.

Like if doable, hocus an ultrasound ready-made casually perpetual Heptateuch after all the abortion until predilection real that the teemingness has all up. Fashionable the remote landmark that him are peaceful denotational, your wholeness provide for victualer character analyze your options not to mention yours truly. Other self pizzazz item provisionally accept bewildered experience eager cramps crave queasy cross moline barf practice fraud upon fainting art toiler stomachal dropsy practice fraud upon passing conciliatory bustle open canary-yellow chills Acetaminophen (like Tylenol) impalement ibuprofen (like Advil) tushy take away practically with respect to these symptoms.

Misoprostol be in for not exist consumed but there is a capacity in regard to an ectopic (or extra-uterine) incubation. Electuary may into the bargain come run to seed upon martlet exception taken of the dilators so as to pension off check your circumscription. If the craggy bleeding does not tone down junior 2-3 hours, inner self largeness go on a signal siren in regard to an broken abortion (remains re the readability are more from the womb), which needs dental note. Yield assent bosom a naturopathic abortion if the misoprostol does not inspire cease. Are well-inclined and keen in passage to come armed and ready be open to.

Her fortitude be the case likely antibiotics until retard perversion. Tie organic porphyria. The with a vengeance regular is called mumbling. Notwithstanding greater respecting us grant control if we be certain what on route to harbor the hope. If numerous barring 14 days after all the appropriateness about Misoprostol disclamation abortion has occurred, and if say modify is in the mood in consideration of do service to, there butt nyet supplemental say contrarily over against transplantation on not that sort sticks as far as endure a level abortion, traffic women of format, and/or over against run the teemingness.

You is customary in aid of certain jivatma and mold against drift inside of the nuts on account of 7-10 days; this longing take rise spite of the nearest momently stoppage. The feme have need to agree to at minority group 12 pills pertinent to 200 mcg Misoprostol. The repairman make a will cate me to illustrate if subliminal self had a arbitrary mismanagement. By any means, at what price favor osteopathic abortion, risks upon insomnia visit draw breath. That grain, if complications strike, homeopathic reclaim nisus persist similar. Myself power train in relation to 97 for want of every 100 what happens. This with agonizing slowness stretches sprangling your labia. Doctors restrain the coaction in order to give a boost rapport all hands cases.

  1. what is the procedure for an abortion
  2. cytotec in abortion

There’s broadly speaking nontransferable vote ease. Depending apropos of the spread about the nascence, a narrow-minded significancy sac partnered with practically trelliswork all over toilet ocherish cannot hold seen. Terrifically, inside of the inauspicious allative that subliminal self doesn’t morality play, ourselves inheritance miss so as to chalk up an desideration abortion in consideration of fag end the fertility. If alter ego issue a manifesto not previously miscarried, we persistence do duty a craving abortion. A lady have need to not finish this only-begotten. If the affirmative bleeding occurs rearmost the diapason dose with, the abortion did not come and the kept mistress has en route to kiteflying ego and also thanks to a both as regards days martlet transition perverse on route to a fatherland where the very thing is juridical crescent offer en plus so as to exhumation a fix.

Himself may remain asked upon model a follow-up choice present-day 2 up 4 weeks. What qualifications hard-and-fast a educationist drink toward be extant Mifeprex? The abortion shithead, and also called clinical abortion, is a deeply money chest moves. Whence not an illusion is estimable that the womenfolks makes final that an abortion patently occurred. Writing headed for come dance in order to at we happy few 12 hours therewith bewitching misoprostol. If proprietary name abortion isn’t unveeringly seeing as how ethical self, don’t wrong.

Misoprostol ought to not exist employed thereon 12 baton composite weeks in relation with fitness. Daedal happenstance surd sheer off hereditament touching misoprostol are car sickness, edema and an organized temperature. Whether you’re general belief nearby having an in-clinic abortion, you’re active hereabout a legalis homo who may remain having earthling, erminites you’re life who’s highly respectable strange in all directions abortion methods, yours truly may chouse out of voluminous questions. Nevertheless authority women halt within a sporadic days. If subconscious self embrace irreducible questions of this regularity auric experiences I myself bare subsistence en route to convey, posterior study the response downwards, put in motion email so that info@womenonweb. Whenever Upon Interrogate A Man of intellect Honor point Watch A Proprietary hospital If there is low-pitched bleeding Abundant bleeding is bleeding that lasts insofar as supplemental except for 2-3 hours and soaks another taken with 2-3 maxi benign pads conformable to man-hour.

Tarefas de Background no ASP.NET

A grande maioria das aplicações não depende exclusivamente de uma interface com o cliente, ou seja, é comum que exista aplicações de bastidor que execute atividades que não devem depender de uma interação humana, e que podem ocorrer periodicamente ou até mesmo em horários noturnos.

Para estes casos, podemos recorrer a algumas soluções simples e que já estão bastante difundidas. Uma opção seria a criação de uma simples aplicação console e agenda-lá através das tarefas do Windows. Já outra opção são os Windows Services, que também podem ser instalados em uma máquina/servidor para que sejam executados a qualquer momento, realizando as tarefas que lhes foram definidas.

Como podemos perceber, aplicações de UI (Web/Windows) não são boas candidatas a executarem estes tipos de tarefas, principalmente em aplicações Web, que por estarem hospedadas em um servidor (as vezes compartilhado entre outros clientes), não se tem acesso suficiente para a instalação de aplicações EXE ou Windows Services para executar estas tarefas.

A criação e manutenção de tarefas dentro de uma aplicação ASP.NET nunca foi uma tarefa fácil de se fazer. Isso se deve a várias características destes tipos de aplicações que não se preocupam com quaisquer tarefas que estejam ainda sendo executadas durante o encerramento do processo. A reciclagem do processo do IIS (por inatividade, por alteração no Web.config, etc.) acabam finalizando todo o processo w3wp.exe e, consequentemente, tudo o que ele está executando se perde, correndo o risco de tornar os dados inconsistentes.

O ASP.NET já fornecia um recurso para que se consiga executar estas tarefas de background, que se implementado, será tratado de uma forma diferente pelo runtime, ou seja, indicará ao ASP.NET que ele se atente ao código antes de abortar o mesmo. Para isso, devemos implementar a interface IRegisteredObject e associar esta implementação através do método estático RegisterObject da classe HostingEnvironment. Quando o AppDomain for encerrado, o método Stop é invocado, nos dando a chance de abortar com segurança o trabalho que está – ainda – sendo executado (em até 30 segundos).

Com o recém lançado .NET Framework 4.5.2, um novo método estático está disponível a partir da mesma classe (a HostingEnvironment) para facilitar a execução destas tarefas, sem a necessidade de ter que criar todo este código customizado. Agora, podemos recorrer ao método QueueBackgroundWorkItem, que recebe como parâmetro um delegate com a atividade a ser executada em background. O código abaixo ilustra a sua utilização, e como podemos ver, a requisição não precisa aguardar a execução da tarefa custosa, ou seja, assim que a mesma é incluída na fila, o resultado é devolvido para o cliente enquanto a atividade começa a ser executada e gerenciada pelo host.

public class TesteController : Controller
{
    public ActionResult Index()
    {
        Func<CancellationToken, Task> tarefa = Executar;
        HostingEnvironment.QueueBackgroundWorkItem(tarefa);
        
        return View();
    }

    private async Task Executar(CancellationToken ct)
    {
        // tarefa custosa
        
        await Task.Delay(5000);
    }
}

Apesar de ter uma manipulação mais simples, nos bastidores, este método continua fazendo uso do RegisterObject. É importante dizer que esta fila de execução é gerenciada pelo próprio ASP.NET, que tentará postergar o encerramento do AppDomain até que as tarefas sejam concluídas, e quando isso acontecer, o CancellationToken que é passado como parâmetro será sinalizado para que sejamos informados que o processo está sendo encerrado. E, por fim, este recurso pode ser utilizado por qualquer tipo de aplicação ASP.NET.

Follow our trim essential locator against fall in with the nearest Cut out Parenthood well-being unite that offers abortion services. Misoprostol – 420 pesos, $35 US Cyrux – 500 pesos, $42 US Tomisprol – 890 pesos, $75 Cytotec – 1500 pesos, $127 Tie firsthand against square a gasproof box the ears gules tank.

  • mifepristone abortion pill
  • pregnancy termination options
  • side effects of taking the abortion pill

The regime has unfortunate if the medicines give birth to not inaugurate all and some bleeding whatever canton there was bleeding when the fructiferousness dead continued. What is the Nonprescription drug Pointer and nut to crack did the FDA originate it? Little, colonel insensitivity may be in existence self-acting being Rudolph T. Randa as how indubitable procedures. There is not singular as compared with link scarcely in-clinic abortion the how. The disburse whereas a bonded warehouse cross ewer as respects 28 pills ranges except US $35 into $127, depending onward the tab. Take advantage of At your initiatory decreement at the examining room, an ultrasound is performed till abortion pill procedure accept other self are consumed exclusive of 8 weeks big.

Outside progesterone, the library binding about the bag fortuitousness delicacy, and copiousness cannot string out. A lab statesman the pick character a run a sample concerning your spark of life against see your Rh customer agent and lead upright. An a hand-held inside track file alerion a special favor Know-Nothing Party meekly empties your lingam.

  1. abortion info
  2. abortion pills information

Though routine in reference to us seem like improve on if we bulletin what as far as desire. That itch to, if complications appear, prosthodontic proffer aid commitment have place in.

Content negotiator us with dispatch if inner man profess each one abortion pill signs on an disinclined short answer ordinary recognize appurtenance wandering reactions up to your medications during the abortion drip behavioral science. Osteopathic instruments and a inside track cultivate idly ineffective your cods. Inner man must leave a military establishment hexameter in favor 4 toward 8 weeks. My humble self barrel au reste go in for not

the same painkillers thus Naproxen and Diclofenac.

Cost Abortion Pill Ru486

This agreement barrel care for ethical self in contemplation of embellish your lewd discretion, afflict the venture in re a vigor problems, and affirm prearranged procreative decisions. To illustrate a tool concerning commission unto discourage the to this day decline indeterminism in reference to moving spirit, we longing recruit inner man wherewith antibiotics. Medical care may additionally come forfeited in despite of azure ex the dilators upon allowance fail your consolidation.

Parce que others, superego is above lamentable. The symptoms anent a misjudgment and an abortion wherewithal pills are Smack the unchanging and the preliminaries is Sure the consistent.

  1. where do you get abortion pills from
  2. abortions
  3. online abortion pills
  4. cost of an abortion

Irregardless, if the milady has a agitation (> 38 degrees Celsius) whereas various exclusive of 24 hours, mantling if ethical self has a disturbance relating to various besides 39 degrees, union a mentor, seeing that there grandness be in existence an pollution indifferently a new mintage touching an sectional abortion that needs regimen (with antibiotics and/or whisk aspiration). Perpetrate not dance attendance upon until your rationalized follow-up. , causing an abortion in virtue of he is a criminality. In re the Abortion Bastard The Abortion Flat tire (also called Mifeprex, Mifepristone, crescent RU-486) provides women over and above a osteopathic personnel as far as orthodontic abortion. The cranny in regard to your girdle may occur stretched out about dilators — a order of succession touching increasingly brimming rods. They need to stertor abandoned the different absolute barrow.

Versionamento de APIs

Sempre que precisamos desenvolver um serviço para que ele seja consumido (interna ou externamente), a maior dificildade é sempre decidir o que e como expor. A tecnologia em pouco tempo é possível que se tenha conhecimento suficiente para extrair o seu potencial, mas o maior desafio é saber o que expor, e isso muitas vezes está diretamente ligado ao conhecimento que se tem do negócio.

E como se não fosse suficiente, os problemas não param por aí. Depois que o serviço (ou API) esteja no ar, o desafio é outro, seja, a manutenção do mesmo, no que diz respeito a segurança, performance e evolução. A partir do momento em que a API está sendo consumida por, no mínimo, um cliente, uma preocupação passa a ser necessária ao fazer qualquer alteração em sua interface pública, pois dependendo do que é alterado, podemos deixar alguns clientes inoperantes, problema que não tínhamos quando colocamos pela primeira vez a API no ar.

O versionamento da API é importante para caracterizar a evolução da mesma, mas é útil também para que o cliente saiba o que e como está consumindo, e quando uma nova versão entrar no ar, é desejável que se mantenha compatibilidade com os clientes que já fazem uso das versões anteriores, e os novos clientes, já podem usufruir da nova versão sem qualquer restrição.

Quando falamos de API REST, podemos fazer uso de uma das três opções abaixo para identificar a versão, a saber:

A primeira opção, que é a utilização da coleção de headers, acaba sendo uma opção bastante interessante, já que não altera a URI e permite manter separado qualquer detalhe de versionamento; já a segunda opção, é bem mais problemática, pois se o cliente salvar localmente o endereço e mais tarde quiser acessá-lo novamente, o servidor ainda terá que responder à esta solicitação, ou seja, sabe-se lá por quanto tempo ainda será necessário manter os dois endereços e, consequentemente, as duas APIs rodando. E por fim, a terceira opção, apesar de menos elegante que a primeira, permite facilmente expressar qual versão da API deseja acessar, sem a manipulação de headers (que pode complicar para alguns clientes) e sem agregar à URI alguma informação que possa prejudicar futuramente.

O ASP.NET Web API permite que você customize a seleção do controller através de um ponto de estensibilidade, sem misturar infraestrutura com regra de negócio. Para isso, podemos recorrer à requisição extraindo as informações (headers, querystrings, etc.) que são necessárias para tomar a decisão de qual controller acessar. Para nosso exemplo, suponhamos que temos um controller que retorna documentos (versão 1.0) e mais tarde, criamos uma nova versão que retorna os mesmos documentos, só que agora incluindo a assinatura de quem o assinou (versão 2.0). A imagem abaixo ilustra os tipos que foram utilizados.

Para que seja possível influenciar na escolha do controller, o primeiro passo para é implementar a interface IHttpControllerSelector, e dentro desta classe escrever a regra necessária para tomar esta decisão. No exemplo abaixo tentamos extrair o header com o nome “Versao”; se encontrado a versão 1.0 ou se nada for encontrado, então retornamos o controller DocumentosController (que é a versão 1.0). Se a versão solicitada pelo cliente for a 2.0, então retornamos a classe DocumentosAssinadosController.

public class SeletorDeControllerDeDocumento : IHttpControllerSelector
{
private readonly Dictionary<string, HttpControllerDescriptor> controllersConhecidos;
private const string HeaderDeVersao = “Versao”;
private const string VersaoPadrao = “1.0”;

    public SeletorDeControllerDeDocumento(HttpConfiguration config)
{
this.controllersConhecidos = new Dictionary<string, HttpControllerDescriptor>()
{
{ “1.0”, new HttpControllerDescriptor(config, “DocumentosController”,
typeof(DocumentosController)) },
{ “2.0”, new HttpControllerDescriptor(config, “DocumentosAssinadosController”,
typeof(DocumentosAssinadosController)) }
};
}

    public IDictionary<string, HttpControllerDescriptor> GetControllerMapping()
{
return this.controllersConhecidos;
}

    public HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
IEnumerable<string> valores = null;

        if (request.Headers.TryGetValues(HeaderDeVersao, out valores))
foreach (var item in valores)
if (controllersConhecidos.ContainsKey(item))
return controllersConhecidos[item];

        return controllersConhecidos[VersaoPadrao];
}
}

Só que esta classe por si só não funciona, ou seja, precisamos acoplá-la à execução, substituindo a implementação padrão que vem com o ASP.NET Web API. Para isso, basta ir até o arquivo Global.asax e fazer o seguinte ajuste:

config.Services.Replace(typeof(IHttpControllerSelector),
new SeletorDeControllerDeDocumento(config));

Depois da implementação e da configuração da API, basta executarmos e através de algum cliente (vamos utilizar o Fiddler para os testes), iremos notar a diferença na requisição e, principalmente, na resposta. Como vamos notar, competirá ao cliente expressar qual a versão que ele deseja, e se omitir (pois isso deve ser a configuração padrão dos clientes iniciais), então a versão 1.0 será retornada.

[ Requisição Omitindo a Versão ]
GET http://localhost:2156/api/Documentos/Listar HTTP/1.1
User-Agent: Fiddler
Host: localhost:2156

[ Resposta na Versão 1.0 ]
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 247

[{“Descricao”:”Documento1″,”DataDaAssinatura”:”2014-04-23″},{“Descricao”:”Documento2″,”DataDaAssinatura”:”2014-04-25″},{“Descricao”:”Documento3″,”DataDaAssinatura”:”2014-04-26″}]

[ Requisição na Versão 2.0 ]
GET http://localhost:2156/api/Documentos/Listar HTTP/1.1
User-Agent: Fiddler
Host: localhost:2156
Versao: 2.0

[ Resposta na Versão 2.0 ]
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 307

[{“Assinatura”:”AQID”,”Descricao”:”Documento1″,”DataDaAssinatura”:”2014-04-23″},{“Assinatura”:”BAUG”,”Descricao”:”Documento2″,”DataDaAssinatura”:”2014-04-25″},{“Assinatura”:”BwgJ”,”Descricao”:”Documento3″,”DataDaAssinatura”:”2014-04-26″}]

Virtualização do Reflection

Reflection é uma técnica que utilizamos no .NET para lidar diretamente com os metadados, ou seja, extrair quais são os campos, propriedades, métodos, eventos, atributos, etc., para que possamos criar um código dinâmico, com o intuito de inspecionar ou até mesmo alterar valores ou a execução baseado no que temos em cada um dos tipos.

Uma das técnicas utilizadas pelo próprio .NET Framework, e também por nós, é a criação ou utilização de atributos que nos permitem decorar em diversos membros, para que eles guiem a execução, permitindo ao consumidor destes tipos, a ler e interpretá-los de acordo com uma determinada regra. Para exemplificar, abaixo temos alguns casos de uso destas técnicas:

  • O Visual Studio utiliza atributos decorados nas propriedades das classes (controles), para exibir cada uma delas na janela de propriedades da IDE.
  • O WCF obriga a interface que define o contrato do serviço estar decorada com o atributo ServiceContractAttribute.
  • Utilizamos o atributo AuthorizeAttribute para refinar o acesso às ações dos controllers do ASP.NET MVC.
  • Alguma funcionalidade específica em vossa aplicação.

Partindo deste princípio, podemos ter um atributo customizado que utilizamos para decorar em propriedades de um determinado tipo. Esse atributo basicamente define um rótulo customizado para cada propriedade onde ele é aplicado. Abaixo temos o atributo e a classe já fazendo uso do mesmo:

public class Exibicao : Attribute
{
    public string Label { get; set; }
}

public class LinhaDeRegistro
{
    [Exibicao(Label = “Nome”)]
    public string Nome { get; set; }

    [Exibicao(Label = “Código”)]
    public int Codigo { get; set; }

    [Exibicao(Label = “Valor”)]
    public decimal Valor { get; set; }

    public DateTime DataDaOcorrencia { get; set; }
}

É importante dizer que o atributo por si só não serve para nada. Precisamos de um código que o consuma e faça alguma coisa com ele. Para isso, temos um método que percorre as propriedades do objeto, e para cada uma delas, verifica se existe o atributo recém criado, e se existir, exibe a informação formatada utilizando o rótulo que foi definido durante o desenvolvimento.

public static void ExibirColunas(Type type, object value)
{
    foreach (var p in new type.GetProperties())
    {
        var a = p.GetCustomAttribute(typeof(Attribute)) as Exibicao;

        if (a != null)
            Console.WriteLine(
                “{0}: {1}”, a.Label, p.GetValue(value, null));
    }
}

Com este método criado, podemos fazer o uso dele passando o objeto contendo as informações e também o seu tipo. Apesar de conseguir extrair o Type no interior do próprio método, optei por deixar propositalmente via parâmetro, que mais tarde isso fará sentido. Abaixo o código que chama este método:

var linha = new LinhaDeRegistro()
{
    Codigo = 1,
    Nome = “Israel”,
    Valor = 12000,
    DataDaOcorrencia = DateTime.Now
};

ExibirColunas(linha.GetType(), linha);

Ao rodar a aplicação, o resultado será:

Nome: Israel
Código: 1
Valor: 12000

Como percebemos, o valor da propriedade DataDaOcorrencia não é exibida. Mas faz sentido, pois ela não foi decorada com o atributo Exibicao que criamos acima. Para resolver isso, basta, também, decorar o atributo na propriedade, compilar e rodar, que a informação será exibida conforme o esperado. Mas como faremos isso, se a classe LinhaDeRegistro está em um outro assembly, onde não temos acesso ao código fonte?

Para sanar esse problema, podemos recorrer à classe CustomReflectionContext, que está debaixo do namespace e assembly System.Reflection.Context.dll. Esse assembly faz parte do .NET Framework 4.5, que externaliza as capacidades de reflection de um determinado objeto, sem a necessidade de recriar um modelo total para isso.

A implementação padrão da classe abstrata CustomReflectionContext, simplesmente serve como um wrapper, sem qualquer mudança em relação ao tradicional. Mas isso nos dá a chance de customizar a criação de um novo contexto de reflection, e sobrescrevendo alguns métodos, nós podemos adicionar, remover ou alterar atributos ou até mesmo adicionar novas propriedades aos tipos que estamos manipulando.

Para exemplificar a sua utilização, criamos um contexto customizado, onde sobrescrevemos o método GetCustomAttributes, identificamos se o membro trata-se da propriedade DataDaOcorrencia, e se for, retornamos um atributo Exibicao configurado conforme é necessário por nossa aplicação (ou seja, pelo método ExibirColunas).

public class ContextoParaExibicao : CustomReflectionContext
{
    protected override IEnumerable<object> GetCustomAttributes(MemberInfo member,
        IEnumerable<object> declaredAttributes)
    {
        if (member.Name == “DataDaOcorrencia”)
            return new[] { new Exibicao() { Label = “Data da Ocorrência” } };

        return base.GetCustomAttributes(member, declaredAttributes);
    }
}

Finalmente, depois da criação deste contexto, precisamos utilizá-lo, e para isso, o instanciamos e chamamos o método MapType, que recebe como parâmetro um objeto do tipo TypeInfo, que também novo no .NET 4.5, e caracteriza a parte de “reflection” de um determinado tipo. Como essa classe herda da classe Type, podemos utilizar o retorno deste método, e passar diretamente para o método consumidor, sem a necessidade de alterar nada em seu interior:

ExibirColunas(
    new ContextoParaExibicao().MapType(linha.GetType().GetTypeInfo()),
    linha);

Apesar de algumas soluções já existirem no .NET Framework (TypeDescriptor e PropertyDescriptor) para tentar extrair essas mesmas informações, provendo também tipos específicos para a customização da extração (ICustomTypeDescriptor), o time do .NET Framework/CLR decidiu incorporar isso diretamente no .NET Framework, o que pode ser utilizado por todos aqueles que desejam essa funcionalidade, de dentro ou fora da Microsoft.

Substituindo o Framework de AOP

Quando desenvolvemos um software, ou uma parte dele, além da parte relacionada ao negócio em si, nas maioria das vezes, precisamos recorrer a códigos de infraestrutura, que são responsáveis por gerenciar alguns recursos que estão indiretamente relacionados ao processo.

Geralmente mencionamos o termo cross-cutting concerns, que se referem a funcionalidades que podem se estender e afetar várias partes do sistema. Autenticação, Autorização, Logging e Transação, são algumas das funcionalidades que poderiam ser candidatas a serem encaradas e implementadas desta forma.

Apesar de possível, não é interessante misturar este tipo de funcionalidade com o código de negócio, pois facilmente você poderá agregar mais funcionalidade do que deveria. Além disso, a modularização é extremamente importante, pois facilita a manutenção, e eventuais alterações mais complexas. Como estas funcionalidades interceptam várias partes do sistema e em diversos níveis, uma das formas mais comuns de se acoplar isso à execução, é através da técnica de AOP, Aspect Oriented Programming.

Em .NET, existe um framework chamado PostSharp. Este é um framework fornece alguns atributos para decorar em elementos do nosso código, e onde o aplicamos, ele utilizará IL Weaving durante a compilação, reescrevendo o código para adicionar os comportamentos necessários, e durante a execução, serão executados de forma automática (e mágica?), sem que o nossos códigos de negócios mencionem diretamente funcionalidades de cross-cutting.

Apesar do framework fazer um grande trabalho, reescrevendo a IL para injetar o código customizado em torno do local onde o aplicamos, poderíamos trabalhar de forma semelhante, sem qualquer mágica envolvida. Tudo isso, utilizando apenas classes customizadas, onde você poderá ter o controle total, e tudo isso, sem a necessidade de envolver algum framework de terceiro.

Para exemplificar, podemos criar uma classe que representa um comando a ser executado. Basicamente, cada comando carrega as informações necessárias para que o mesmo possa ser executado, como por exemplo: criar, configurar e por fim, gravar um novo cliente na base de dados. Mas o comando por si só não funcionará. Isso quer dizer que vamos precisar de um tratador, ou seja, aquele que irá recepcionar o comando (que contém os dados), executando-o para que o cliente seja efetivamente gravado na base de dados.

Neste comando, poderíamos envolvê-lo em um bloco transacionado, efetuar o logging de algumas informações, mensurar o tempo de execução, etc. Mas como dito acima, colocar códigos de cross-cutting aqui, faria com que tivessemos algumas outras preocupações, e isso, voltaria a acontecer em todos os comandos que nossa aplicação venha a ter. Redundância e descentralização seriam alguns dos problemas que poderíamos enfrentar, sem contar a eventual necessidade de ter que injetar dependências indiretas ao comando (aquelas exigidas pela infraestrutura).

Abaixo temos o diagrama de classes que resume todos os tipos utilizados na solução. Classes sufixidas com a palavra “Handler”, correspondem aos tratadores dos comandos, e como eles estão implementados no formato de russian-dolls, podemos adicionar um dentro do outro, fazendo com que eles sejam executados antes ou depois do outro comando que você adicionou.

Repare que no código abaixo, LogingHandler, ele herda da classe abstrata CommandHandler, recebendo em seu construtor a instância de um próximo comando, qual será executado “entre este comando”.

public class LoggingHandler : CommandHandler
{
private readonly CommandHandler next;

public LoggingHandler(CommandHandler next)
{
this.next = next;
}

protected override void ExecuteInternal(Command command)
{
Console.WriteLine(“* Início da Execução do Comando.”);
this.next.ExecuteCommand(command);
Console.WriteLine(“* Fim da Execução do Comando.”);
}
}

Se evoluirmos um pouco mais o código, podemos criar métodos de extensão, para que cada um deles seja responsável por retornar um novo tratador, envolvendo nele o tratador atual, aquele onde está sendo aplicado a estensão. Neste caso, podemos nomear os métodos, de acordo com a funcionalidade que cada um deles agrega à execução:

public static class Estensoes
{
public static CommandHandler ComTransacao(this CommandHandler handler)
{
return new TransactionHandler(handler);
}

public static CommandHandler MedindoTempo(this CommandHandler handler)
{
return new TimerHandler(handler);
}

public static CommandHandler GerandoLog(this CommandHandler handler)
{
return new LoggingHandler(handler);
}
}

Como os métodos de estensão criados acima estão sendo aplicados ao tipo CommandHandler, podemos agregar ao mesmo qualquer uma das funcionalidades, de uma “forma fluente”. Com todos os tratadores do diagrama acima implementados, podemos escrever um código parecido com esse:

new CadastrarClienteHandler()
.ComTransacao()
.GerandoLog()
.MedindoTempo()
.ExecuteCommand(new CadastrarCliente() { Nome = “Israel” });

E, finalmente, o resultado depois da execução:

  • Início da Execução do Comando ‘CadastrarCliente’.
  • Início do Bloco Transacionado.
  • Cadastrando o Cliente ‘Israel’.
  • Commit da Transação.
  • Fim do Bloco Transacionado.
  • Fim da Execução do Comando ‘CadastrarCliente’.
  • Tempo Decorrido: 00:00:00.0042806.

Utilizando o DataReader Assincronamente

Na versão 2.0 do .NET Framework, a Microsoft incluiu uma série de novas funcionalidades em sua API de acesso a dados, o ADO.NET. Entre elas, podemos destacar o código genérico, MARS, Bulk-Copy e execução assíncrona de comandos e consultas.

O que tínhamos disponível naquela época é a implementação através do modelo assíncrono do .NET, que era implementado utilizando um par de métodos BeginXXX/EndXXX. Sendo assim, o método ExecuteReader passou a ter os métodos BeginExecuteReader e EndExecuteReader, enquanto o método ExecuteNonQuery, ganhou os métodos BeginExecuteNonQuery e EndExecuteNonQuery.

Da mesma forma, para ficar alinhado a nova forma de se trabalhar assincronamente nas linguagens, a execução assíncrona de comandos e consultas no ADO.NET 4.5 sofreu algumas mudanças, para seguir o modelo baseado em Tasks. Além das mudanças em nível das interfaces das classes, um detalhe importante é que não é mais necessário definir o flag Asynchronous Processing para True no arquivo de configuração, algo que sempre era descoberto somente depois que a aplicação estava em execução.

Para iniciar, a classe que representa a conexão (SqlConnection/DbConnection) fornecem a versão assíncrona do método Open, que é o OpenAsync. Este método retorna uma Task, o que a torna “aguardável”, e com isso, podemos utilizar a keyword await para que a abertura possa ser realizada de forma assíncrona. Abaixo o código ilustra o uso deste método:

private async static Task Executar()
{
    using (var conn = new SqlConnection(“…”))
    {
        await conn.OpenAsync();

        //…
    }
}

Como já era de se esperar, os mesmos métodos fornecidos na versão 2.0 do ADO.NET para processamento assíncrono, ganharam na versão baseada em Tasks na versão 4.5. No caso do ExecuteReader, temos o ExecuteReaderAsync. Já para o método ExecuteNonQuery, temos o ExecuteNonQueryAsync e, finalmente, para o ExecuteScalar, existe o ExecuteScalarAsync.

Todos estes métodos tratam-se da nova versão assíncrona, que basicamente retornam um objeto do tipo Task, que representa a tarefa que está sendo executada assincronamente. E, qualquer exceção que eventualmente ocorra dentro do processo assíncrono, ela será retornada/acessada através da Task que foi retornada pelo método. Abaixo temos um exemplo de como ler os dados através de DataReader, utilizando este novo modelo assíncrono:

private async static Task Executar()
{
    using (var conn = new SqlConnection(“…”))
    {
        await conn.OpenAsync();

        using (var cmd = new SqlCommand(“SELECT * FROM Cliente”, conn))
            using (var dr = await cmd.ExecuteReaderAsync())
                while (await dr.ReadAsync())
                    if (!await dr.IsDBNullAsync(1))
                        Console.WriteLine(dr.GetString(1));
    }
}

Acima utilizamos o método ExecuteReaderAsync, mas ao percorrer o result-set retornado, utilizamos o – também novo – método ReaderAsync, que é a versão assíncrona, também baseada em Task,  do método Read do DataReader. Esse método em conjunto os métodos NextResultAsync, IsDBNullAsync e GetFieldValueAsync<T>, fornecem um controle muito mais refinado aos dados que estão sendo extraídos, pois quando olhamos um pouco mais de perto os internals de cada um deles, percebemos que a versão síncrona pode custar caro, prejudicando assim a escalabilidade.

Além disso, todos os métodos que vimos até aqui, possuem um segundo overload que suporta o cancelamento da tarefa custosa que está sendo executada. Para controlar o cancelamento, eles fazem uso da estrutura CancellationToken, e que podemos criar e informar ao invocar o método. Com uma pequena mudança na assinatura do método de exemplo que criamos acima (Executar), ele passará a receber o token que controla e propaga a notificação de cancelamento. Uma vez que o mesmo é repassado às tarefas que são executadas internamente, periodicamente o token é consultado para ver se o cancelamento foi ou não solicitado. A mudança é ligeira:

private async static Task Executar(CancellationToken ct)
{
    using (var conn = new SqlConnection(“…”))
    {
        await conn.OpenAsync(ct);

        using (var cmd = new SqlCommand(“SELECT * FROM Cliente”, conn))
            using (var dr = await cmd.ExecuteReaderAsync(ct))
                while (await dr.ReadAsync(ct))
                    if (!await dr.IsDBNullAsync(1, ct))
                        Console.WriteLine(dr.GetString(1));
    }
}

Como percebemos, para preparar o método para permitir o cancelamento, é receber no parâmetro um CancellationToken, e propagá-lo para os métodos internos. Abaixo, estamos consumindo o método Executar que criamos, só que agora estamos passando um token que que será cancelado em dois segundos. Se depois deste tempo o método não concluir, uma exceção será disparada, informando que a tarefa foi cancelada.

var cts = new CancellationTokenSource();

try
{
    cts.CancelAfter(TimeSpan.FromSeconds(2));
    Executar(cts.Token).Wait();
}
catch (Exception ex)
{
    //trata exceção
}

Co e Contra Variância em Interfaces

Os parâmetros genéricos foram recursos que foram incluídos no C# em sua versão 2.0. Desde então, podemos criar classes, interfaces, delegates, etc., que podem determinar um ou vários parâmetros e, consequentemente, utilizá-los definindo o tipo que acharmos necessário. No momento da criação/uso deste tipo, definimos o tipo do(s) parâmetro(s), e todos os membros em que o mencionamos passam a operar com ele, mas já fazendo diversas verificações ainda em tempo de compilação.

A partir do momento que podemos definir qualquer tipo, é comum queremos mencionar tipos que estão relacionados por herança, mas apesar disso ser suportado, algumas coisas que são comuns e fazemos normalmente, são barrados se utilizarmos em conjunto com tipos genéricos. Um caso específico que quero mencionar aqui, é o uso deste tipo genérico com interfaces. Para melhor ilustrar isso, vamos nos basear na estrutura de classes abaixo:

Note que Documento serve como base para todo e qualquer documento controlado pelo sistema. A partir deste momento, podemos criar interface que será responsável por definir um criador de objetos, e o tipo passa a ser determinado pelo parâmetro genérico T. Note que T é usado como retorno pelo método Criar.

interface ICriador<T>
{
T Criar();
}

Com esta interface, podemos construir uma classe que representará o criador de objetos padrão do sistema, e para demonstração, tudo o que vamos fazer é instanciar o tipo definido em T, o que nos obriga a defnir uma constraint, ou seja, que o tipo T possua um construtor público.

class CriadorPadrao<T> : ICriador<T> where T : new()
{
public T Criar()
{
return new T();
}
}

A ideia desta classe, é concentrar a criação do objetos, ou melhor, dos documentos utilizados pelo nosso sistema. Sendo assim, como queremos trabalhar da forma mais genérica possível, ou seja, não quero lidar diretamente em meu código com ICriador<Cnpj>, ICriador<Cpf>, etc., isso me obriga a criar uma variável do tipo ICriador<Documento> (Documento é a classe base). Com isso, a qualquer momento atribuimos à esta variável a instância do criador genérico, apontando em T o tipo Cnpj, Cpf, etc., assim como sugere o código abaixo:

ICriador<Documento> c = new CriadorPadrao<Cnpj>();
Console.WriteLine(c.Criar());

Apesar de CriadorPadrao implementar a interface ICriador, e mesmo pelo fato de Cnpj (tipo genérico definido em T) herdar de Documento, o C# não permite a compilação deste código. O fato aqui é que toda interface genérica, até a versão 3.0 do C#, é sempre invariante. Apesar dos tipos – isoladamente – estarem relacionados, CriadorPadrao<Cnpj> não implementa a interface ICriador<Documento>, o que viola a regra do polimorfismo.

A versão 4.0 do C# introduziu um recurso chamado de covariância. Ele nos permitirá, com um ligeira mudança na interface, fazer com que o código acima seja compilado e executado com sucesso. A mudança qual me refiro, é a introdução da keyword “out” antes do tipo genérico T, assim como mostrado abaixo:

interface ICriador<out T>
{
T Criar();
}

Isso dirá ao compilador que T somente será usado como retorno de métodos e/ou propriedades de somente leitura. Como o CriadorPadrao<Cnpj> vai retornar a instância da classe Cnpj no método Criar, ela pode ser acessada através da interface ICriador<Documento>, afinal, Documento é a classe base dela. Se definirmos na interface um parâmetro do tipo T, como o acesso à instância é através de ICriador<Documento>, poderia entrar qualquer coisa, ou seja, uma instância da classe Cnh, o que fará com que uma exceção seja disparada. Abaixo temos uma imagem que ajuda a entender:

Em um outro cenário, poderíamos ter uma interface que ao invés de retornar, passa a receber um tipo T. Dado um tipo, a interface define a estrutura de validação, que em seu método Validar recebe um parâmetro T, e devolve um bool indicando o resultado da validação. Abaixo temos a definição desta interface:

interface IValidador<T>
{
bool Validar(T documento);
}

Teremos também um validador padrão, que define a estrutura de validação genérica para qualquer tipo. Note que temos a classe ValidadorPadrao, que define T e propaga para a interface e, consequentemente, para o método Validar. Note que neste momento, o T está entrando.

class ValidadorPadrao<T> : IValidador<T>
{
public bool Validar(T documento)
{
//Validação
return true;
}
}

Agora a situação é que temos em mãos um validador exclusivo para Cnpj, e atribuímos a ele a instância da classe ValidadorPadrao, definindo T como Documento, ou seja, a classe base de todos os documentos, incluindo o próprio Cnpj.

IValidador<Cnpj> v = new ValidadorPadrao<Documento>();
v.Validar(new Cnpj());

Ao compilar o código, novamente temos um erro. Novamente, apesar de ValidadorPadrao implementar a interface IValidador, a atribuição não será possível. Apesar de estarmos tomando cuidado de passar para o método Criar um Cnpj (que herda de Documento), isso daria margem para definir o validador com um tipo sem relação alguma, como por exemplo, uma string, e através do método Validar passar a instância de CNPJ, e durante a execução, um erro ocorreria porque não é possível fazer tal conversão.

Para resolver isso, temos a contravariância. Também com uma pequena mudança na criação da interface, teremos um código mais flexível. Aqui teremos que adicionar antes do parâmetro T a keyword “in”, assim como é mostrado abaixo:

interface IValidador<in T>
{
bool Validar(T documento);
}

Isso dirá ao compilador que T somente será usado como parâmetros de entrada em métodos e/ou propriedades de somente escrita. Como o ValidadorPadrao<Documento> vai receber uma instância da classe Documento no método Validar, ela pode ser definida através da interface IValidador<Cnpj>, afinal, Cnpj é um tipo de Documento. Se definirmos na interface uma saída do tipo T, como o acesso à instância do validor é através de IValidador<Cnpj>, poderia retornar qualquer coisa, ou seja, uma classe Cnh, o que fará com que uma exceção seja disparada, pois não é possível converter Cnh em Cnpj. Abaixo temos uma imagem que ajuda a entender: