-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfeed.xml
More file actions
768 lines (570 loc) · 36.8 KB
/
feed.xml
File metadata and controls
768 lines (570 loc) · 36.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Nilson Junior</title>
<description>Desenvolvimento web, .net and more</description>
<link>http://nilsonsrjunior.net/</link>
<atom:link href="http://nilsonsrjunior.net/feed.xml" rel="self" type="application/rss+xml" />
<pubDate>Fri, 11 Dec 2015 10:23:41 -0200</pubDate>
<lastBuildDate>Fri, 11 Dec 2015 10:23:41 -0200</lastBuildDate>
<generator>Jekyll v2.3.0</generator>
<item>
<title>ASP.NET Web Api 2 - Parte 1</title>
<description><p>Antes de entendermos o que é um serviço <strong>REST</strong> e como ele funciona, temos que saber porque ele foi criado e o que havia antes…</p>
<h1 id="web-services---o-comeo">Web Services - O Começo</h1>
<p>Os chamados web services surgiram para permitir e facilitar a comunicação entre diferentes aplicações que podem estar rodando em diferentes plataformas.</p>
<p>Quando surgiram, foi especificado um protocolo em que as mensagens deveriam ser encapsuladas e uma linguagem em que deveriam ser descritas as interfaces dos serviços.</p>
<p>Este procolo de que estamos falando é o <strong>SOAP (Simple Object Access Protocol)</strong>, e a linguagem em que devem ser descritas as interfaces é chamada de <strong>WSDL (Web Services Description Language)</strong>.</p>
<p>Portanto, vamos imaginar que temos que escrever uma carta. Agora, para facilitar a vida do leitor vamos colocar na primeira página uma especificação das coisas que o leitor vai encontrar no conteúdo da carta.</p>
<p>Por ex.:</p>
<ul>
<li>Senha da minha conta do banco;</li>
<li>Receita de bolo de cenoura;</li>
<li>Como fazer flexões embaixo d’agua;</li>
</ul>
<p>Depois de descritas as coisas que o leitor irá encontrar na nossa carta, podemos escrever o conteúdo nas próximas páginas.</p>
<p>Agora trazendo para os web services, imagine que a especificação do conteúdo da carta é o WSDL e o conteúdo é a mensagem.</p>
<p>E o SOAP ? Não podemos mandar esta carta para alguém se não a colocarmos em um envelope para que ninguém veja logo de cara o que está escrito certo ?</p>
<p>Já entendeu né ? O SOAP é o nosso envelope. E o carteiro ? ninguém perguntou do carteiro… foca no exemplo <strike>obg</strike>.</p>
<p>Tá. Mas porque estamos falando de Web Services, SOAP, WSDL ? <strike>CARMA TREM!</strike></p>
<p>Então, tudo isso era lindo, mas tinha um problema: <a href="http://nilsonsrjunior.net/tag/performance/">PERFORMANCE</a>.</p>
<p>Pois é… aí que os serviços REST entraram com os dois pés no peito.</p>
<h1 id="rest-representation-state-transfer">REST (Representation State Transfer)</h1>
<p>A arquitetura REST elimina toda a complexidade de uma interface de serviço WSDL, protocolo para as mensagens, focando apenas nos <strong>RECURSOS</strong>. Ou seja, temos um recurso e diferentes estados.</p>
<p>Então, na prática, vamos supor que temos a seguinte URI: <a href="http://abobrinhasvoadoras.com.br/tipo">http://abobrinhasvoadoras.com.br/tipo</a>.</p>
<p>Tendo em mente esta URI, podemos dizer que o nosso recurso nesse caso é o <strong>tipo</strong> da abobrinha.</p>
<p>Para o recurso <strong>tipo</strong> podemos executar várias ações sobre ele, ao todo temos oito métodos fornecidos pelo protocolo HTTP, mas os principais são:</p>
<ul>
<li>POST - Cria;</li>
<li>PUT - Atualiza;</li>
<li>GET - Busca;</li>
<li>DELETE - Apaga;</li>
</ul>
<p>Quando estamos trabalhando com os recursos, temos que saber em que formato estes recursos estão para que possamos utilizá-los. Quem define isso é o <strong><em>Content-Type</em></strong> que é enviado no cabeçalho da requisição. Os formatos mais utilizados são XML e JSON.</p>
<p>A arquitetura REST também segue alguns outros princípios, como:</p>
<ul>
<li><strong>Cliente-Servidor sem estado</strong>: cada mensagem HTTP deve ser auto-suficiente, ou seja, nada de ficar dependendo de um estado para poder responder uma requisição ou ficar reaproveitando recursos pela metade no meio do caminho. Existem práticas para manter informação como utilização de <strong>[cookies]</strong>(https://www.google.com.br/webhp?sourceid=chrome-instant&amp;ion=1&amp;espv=2&amp;ie=UTF-8#q=cookies+http) que são permitidas pela arquitetura REST, mas isso é conversa para outro post…;</li>
<li><strong>Cada recurso é unicamente identificado</strong> e direcionado através da <strong>sua URI</strong>.</li>
</ul>
<p>Para vermos a coisa funcionando na prática, se você não possuir uma ferramenta para fazer requisições como <a href="http://www.telerik.com/fiddler">Fiddler</a> ou <a href="https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop">Postman</a>, use este <a href="https://resttesttest.com/">site</a> e faça uma requisição com o método <code>GET</code> e o <code>content-type: application/json</code> para a uri <a href="https://httpbin.org/ip">https://httpbin.org/ip</a>.</p>
<p>Você terá este resultado, no formato JSON:</p>
<pre><code>{
"origin": "189.113.145.110"
}
</code></pre>
<p>Viu só ? não é difícil entender como serviços REST funcionam..</p>
<p>No próximo episódio desta novela: <strong><em>Começando com ASP.NET Web Api 2</em></strong>.</p>
<p>Este post não teve código fonte próprio para eu disponibilizar, mas dá uma passada no meu <a href="https://github.com/nilsonsrjunior">github</a>, tem projetos legais lá.</p>
<p>Faça seu comentário, um grande abraço, e até breve !!!</p>
<strike>To be continued...</strike>
</description>
<pubDate>Mon, 07 Dec 2015 17:00:00 -0200</pubDate>
<link>http://nilsonsrjunior.net/aspnet-web-api-2-parte-1</link>
<guid isPermaLink="true">http://nilsonsrjunior.net/aspnet-web-api-2-parte-1</guid>
<category>web-api</category>
</item>
<item>
<title>Otimizando o Back-End com Cache de Objetos</title>
<description><p>Antes de começarmos a conversa, me responsa duas coisas..</p>
<ul>
<li>
<p>Você se preocupa com a performance da sua aplicação?</p>
</li>
<li>
<p>Você precisa otimizar uma rotina para ganhar mais performance ?</p>
</li>
</ul>
<p>Bom, se você respondeu sim para qualquer uma das perguntas acima, vou te ensinar uma técnica <strike>top</strike> excelente para obter um ganho de performance na sua aplicação: <strong>cacheando objetos</strong>.</p>
<p>Esta técnica nada mais é do que armazenar objetos em memória.</p>
<p>Imagine que na sua tela você carrega uma lista com todas as cidades do Brasil. Vamos fingir que você buscou essa lista no seu banco de dados, ok ?</p>
<p>Se você utilizar o cache de objetos, você pode recuperar essa lista somente uma vez do banco de dados, armazená-la no cache, e toda vez que você precisar, é só pegar de lá, ao invés de ter que abrir uma nova conexão com o banco de dados. Bem melhor né ?</p>
<p>Existem váááárias maneiras e bibliotecas para se implementar o uso de cache, mas eu vou falar da biblioteca System.Runtime.Caching que está presente a partir do .NET framework 4.0.</p>
<p>Se você estiver usando uma versão do .NET framework inferior à 4.0, provavelmente terá que usar a biblioteca System.Web.Caching, que era sua antecessora…</p>
<strike>CODE!!!! THAT IS WHAT I WANT!</strike>
<p>Vamos à implementação..</p>
<p>Ah, só uma coisinha… para esse exemplo eu vou criar uma Web Application MVC, mas se você estiver usando um console, windows forms or wathever, você pode implementar da mesma forma, tranquilo ?</p>
<p>Então vai la: File -&gt; New -&gt; Project -&gt; VisualC#/Web/ASP.NET Web Application -&gt; MVC.</p>
<p>Eu dei o nome da aplicação de UsandoCacheDeObjetos, depois você poderá baixá-la no meu <a href="http://github.com/nilsonsrjunior">github</a>.</p>
<p>Vou adicionar um projeto com o nome UsandoCacheDeObjetos.Cache, para adicionarmos nossa referência da biblioteca do cache, mas isso é só para organizar melhor ok?</p>
<p>Neste pequeno projeto, vamos criar uma classe Cache com o seguinte código:</p>
<pre><code>public class Cache
{
static readonly ObjectCache oCache = MemoryCache.Default;
/// &lt;summary&gt;
/// Recupera o item cacheado
/// &lt;/summary&gt;
/// &lt;typeparam name="T"&gt;Tipo do item cacheado&lt;/typeparam&gt;
/// &lt;param name="key"&gt;Nome do item cacheado&lt;/param&gt;
/// &lt;returns&gt;Tipo do item cacheado&lt;/returns&gt;
public static T Get&lt;T&gt;(string key) where T : class
{
try
{
return (T)oCache[key];
}
catch
{
return null;
}
}
/// &lt;summary&gt;
/// Insere o valor em um cache
/// &lt;/summary&gt;
/// &lt;typeparam name="T"&gt;Tipo do item cacheado&lt;/typeparam&gt;
/// &lt;param name="objectToCache"&gt;Item a ser cacheado&lt;/param&gt;
/// &lt;param name="key"&gt;Nome do item&lt;/param&gt;
public static void Add&lt;T&gt;(T objectToCache, string key) where T : class
{
oCache.Add(key, objectToCache, DateTime.Now.AddDays(30));
}
/// &lt;summary&gt;
/// Remove item do cache
/// &lt;/summary&gt;
/// &lt;param name="key"&gt;Nome do item cacheado&lt;/param&gt;
public static void Clear(string key)
{
oCache.Remove(key);
}
/// &lt;summary&gt;
/// Verifica se o item existe no cache
/// &lt;/summary&gt;
/// &lt;param name="key"&gt;Nome do item cacheado&lt;/param&gt;
/// &lt;returns&gt;&lt;/returns&gt;
public static bool Exists(string key)
{
return oCache.Get(key) != null;
}
/// &lt;summary&gt;
/// Retorna todos os itens cacheados como uma lista pela sua respectiva chave
/// &lt;/summary&gt;
/// &lt;returns&gt;&lt;/returns&gt;
public static List&lt;string&gt; GetAll()
{
return oCache.Select(keyValuePair =&gt; keyValuePair.Key).ToList();
}
}
</code></pre>
<p>Para instanciarmos o cache (da classe <code>System.Runtime.Caching.ObjectCache</code>), precisamos apontar onde esta instância será armazenada, no nosso exemplo, utilizamos a opção Default. Lembrando que podemos ter múltiplas instâncias de cache em uma mesma aplicação.</p>
<p><em>Importante: No nosso exemplo, estamos utilizando uma Web Application, sendo assim, o cache será, por padrão, armazenado no Pool de Aplicativo da sua aplicação no seu IIS. Então tenha em mente que se o pool for reciclado, bye bye cache.</em></p>
<p>Continuando !!! Na HomeController, eu substituí todo o código antigo gerado, por este:</p>
<pre><code>public class HomeController : Controller
{
private IEnumerable&lt;Cliente&gt; clientes;
public IEnumerable&lt;Cliente&gt; Clientes
{
get
{
clientes = Cache.Cache.Get&lt;IEnumerable&lt;Cliente&gt;&gt;("Clientes");
if (clientes == null)
{
clientes = RetornaClientes();
Cache.Cache.Add(clientes, "Clientes");
}
return clientes;
}
set { clientes = value; }
}
public ActionResult Index()
{
Cache.Cache.Clear("Clientes");
var timer = new Stopwatch();
timer.Start();
//Acessando a Propriedade
var testeSemCache = Clientes;
timer.Stop();
var tempoSemCache = timer.Elapsed;
timer.Reset();
timer.Start();
//Acessando a Propriedade
var testeComCache = Clientes;
timer.Stop();
var tempoComCache = timer.Elapsed;
ViewBag.SemCache = tempoSemCache;
ViewBag.ComCache = tempoComCache;
return View(Clientes);
}
private static IEnumerable&lt;Cliente&gt; RetornaClientes()
{
yield return new Cliente { Nome = "Zé das couve", Email = "zedascouve@ze.com.br"};
yield return new Cliente { Nome = "Zé", Email = "ze@ze.com.br" };
yield return new Cliente { Nome = "Teste", Email = "teste@teste.com.br" };
yield return new Cliente { Nome = "Sem ideia", Email = "sem@ideia.com.br" };
yield return new Cliente { Nome = "Sem criatividade", Email = "sem@criatividade.com.br" };
yield return new Cliente { Nome = "Sem paciencia", Email = "sem@paciencia.com.br" };
}
}
</code></pre>
<p>Vamos lá… line by line… na nossa <code>AccountController</code>, notem que eu criei uma propriedade Clientes. No <code>get</code> dessa propriedade eu a pego do cache, se ela for nula, ou seja, ainda não existir, eu retorno a lista de clientes do método <code>RetornaClientes</code>, atribuo no cache e retorno.</p>
<p>No método <code>RetornaClientes</code>, eu estou preenchendo a lista de Cliente com <strong>yield</strong>, se você não conhece este recurso maravilhoso que aumenta sua produtividade, leia este <a href="http://nilsonsrjunior.net/yield-e-de-comer/">post</a>.</p>
<p>Vamos imaginar que o método <code>RetornaClientes</code> fosse buscar esta lista de clientes no banco de dados (para aumentar o tempo de processamento), da forma que implementamos ele só irá ao banco na primeira vez, e depois preencherá a propriedade com a lista que já está no cache.</p>
<p>Wonderful !!! Na nossa action Index, eu criei um <code>Stopwatch</code> para monitorarmos o tempo de carregamento da propriedade com os clientes e fazermos um comparativo quando retornamos do método, e quando retornamos do cache.</p>
<p>Já na View <code>Index</code> da <code>AccountController</code>, referente à este código, eu substitui o conteúdo original por este:</p>
<pre><code>@model IEnumerable&lt;UsandoCacheDeObjetos.Models.Cliente&gt;
@{
ViewBag.Title = "Home Page";
}
&lt;div class="jumbotron"&gt;
&lt;h1&gt;Cacheando Objetos&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="row"&gt;
&lt;div class="col-md-6"&gt;
&lt;h3&gt;&lt;strong&gt;Tempo Sem Cache: @ViewBag.SemCache&lt;/strong&gt;
&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="col-md-6"&gt;
&lt;h3&gt;&lt;strong&gt;Tempo Com Cache: @ViewBag.ComCache&lt;/strong&gt;
&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br/&gt;
&lt;div class="row"&gt;
&lt;div class="col-md-12"&gt;
@foreach (var item in Model)
{
&lt;p&gt;
&lt;strong&gt;Cliente&lt;/strong&gt;: @item.Nome
&lt;strong&gt;E-mail&lt;/strong&gt;: @item.Email
&lt;/p&gt;
}
&lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>O conteúdo desta view é bem simples, irei mostrar o tempo registrado no <code>Stopwatch</code> da controller para compararmos o tempo de preenchimento da variável pegando a lista de clientes do método, e do cache. Além disso, apenas listamos os clientes na tela.</p>
<p>Executando nossa aplicação, o resultado é este:</p>
<p><img src="/img/post/testeperformancecacheobjetos.png" alt="" /></p>
<p>Bom, por hoje é só… como de costume, você pode baixar o código fonte deste post <a href="https://github.com/nilsonsrjunior/blog-projects/tree/master/UsandoCacheDeObjetos">aqui</a>.</p>
<p>Caso tenha alguma dúvida, por favor, coloque nos comentários.</p>
<p>Um grande abraço, e até breve !!!</p>
</description>
<pubDate>Thu, 03 Dec 2015 20:45:00 -0200</pubDate>
<link>http://nilsonsrjunior.net/otimizando-o-back-end-com-cache-de-objetos</link>
<guid isPermaLink="true">http://nilsonsrjunior.net/otimizando-o-back-end-com-cache-de-objetos</guid>
<category>performance</category>
</item>
<item>
<title>Extensions - Aumentando a Produtividade</title>
<description><p>Você já se deparou com uma situação em que tem um monte de classes estáticas para colocar seus métodos comuns do projeto e usá-los sempre que precisa ?
E quando você não lembra em que classe está ?</p>
<p>Ou então a trabalheira de digitar <code>NomeDaClasseEstatica.NomeDoMetodo(Parametro(s));</code></p>
<p>Bem improdutivo, não acha ??</p>
<p>Cara, eu já passei muito por isso. Porém, entretanto, todavia, as <strong>extensions</strong> podem diminuir esse trauma nas nossas vidas!.</p>
<p>Presentes no c# desde a versão 3.0, elas são como métodos estáticos, porém são chamados como se fossem métodos de instância normais. Se você ficou confuso <strike>#keepcalmandreaduntiltheend</strike>, eu vou explicar melhor com exemplos a seguir.</p>
<p>Para criarmos métodos de extensão, eles precisam respeitar algumas regrinhas:</p>
<ul>
<li>
<p>Estar dentro de uma classe estática;</p>
</li>
<li>
<p>Ser estático;</p>
</li>
<li>
<p>Receber como parâmetro o ponteiro da instância “<code>this</code>”</p>
</li>
</ul>
<p>Sustentadas as opções acima, vamos por a mão na massa.</p>
<pre><code>public static class MetodosDeExtensao
{
public static string ToTelefoneFormat(this string telefone)
{
var ddd = telefone.Substring(0,2);
var prefixo = telefone.Substring(2,4);
var sufixo = telefone.Substring(6,4);
return string.Format("({0}) {1}-{2}", ddd, prefixo, sufixo);
}
}
</code></pre>
<p>No exemplo acima o método “<code>ToTelefoneFormat</code>” irá receber uma string com um telefone sem formatação e retorná-lo formatado.</p>
<p>Então para executarmos nosso método de extensão vamos ter o seguinte código:</p>
<pre><code>class Program
{
static void Main(string[] args)
{
var telefone = "4334721597";
telefone = telefone.ToTelefoneFormat();
Console.WriteLine(telefone);
Console.ReadKey();
}
}
</code></pre>
<p>E o resultado disso será: “(43) 3472-1597”.</p>
<p>Mas cadê o parâmetro do método ????</p>
<p>É aí que o <code>this</code> entra. Quando você chama o método através da variável telefone, por meio desta palavra reservada, o compilador irá saber que o parâmetro do método deve ser alimentado com o conteúdo de quem o chamou.</p>
<p>Portanto, uma extension só será possível de ser utilizada e consequentemente visualizada pelo seu intellisense se o tipo de dado que eu estiver usando for o mesmo do parâmetro e retorno da extension.</p>
<p>Para exemplificar a explicação acima, veja a versão atualizada do código:</p>
<pre><code>public static class MetodosDeExtensao
{
public static string ToTelefoneFormat(this string telefone)
{
var ddd = telefone.Substring(0,2);
var prefixo = telefone.Substring(2,4);
var sufixo = telefone.Substring(6,4);
return string.Format("({0}) {1}-{2}", ddd, prefixo, sufixo);
}
public static int ToDobro(this int valor)
{
return valor * 2;
}
}
class Program
{
static void Main(string[] args)
{
//string telefone = "4334721597";
//telefone = telefone.ToTelefoneFormat();
//int valor = 10;
//valor = valor.ToDobro();
string telefone = "4334721597".ToTelefoneFormat();
int valor = 10.ToDobro();
Console.WriteLine(telefone);
Console.WriteLine(valor);
Console.ReadKey();
}
}
</code></pre>
<p>É possível ver também, no exemplo, que não precisamos declarar uma variável com o conteúdo para utilizar a extensão, desde que o tipo de dado seja respeitado como já dito anteriormente.</p>
<p>Desta forma é possível utilizar a extensão do próprio dado, como no caso do telefone e do valor.</p>
<p>Agora pare e imagine a infinidade de utilidades que podemos encontrar usando extensions. Poxa, tenho certeza que pode facilitar nossas vidas e tornar a escrita de código bem mais rápida.</p>
<p>Você pode baixar o código fonte deste post <a href="https://github.com/nilsonsrjunior/blog-projects/tree/master/Extensions">aqui</a>.</p>
<p>Faça seu comentário, um grande abraço, e até breve !!!</p>
</description>
<pubDate>Thu, 03 Dec 2015 20:35:00 -0200</pubDate>
<link>http://nilsonsrjunior.net/extensions-aumentando-a-produtividade</link>
<guid isPermaLink="true">http://nilsonsrjunior.net/extensions-aumentando-a-produtividade</guid>
<category>csharp</category>
</item>
<item>
<title>Enums - Dicas e Truques</title>
<description><p>Enums… você já usou esse cara ?</p>
<p>Se <strong>sim</strong>, dá uma olhada no post porque tem uns macetes bem legais que eu aprendi depois de algum tempo usando enums, e ajudaram pra caramba.</p>
<p>Se <strong>não</strong>, você <strong>precisa</strong> ler este post até o fim, porque este recurso pode te ajudar bastante.</p>
<p>Começando do começo <strike>(não, vamos começar do fim, tonto)</strike>, o enum é a abreviação do que ele é, até mesmo no português, este cara é um enumerador e a função dele é facilitar sua vida quando você precisa declarar uma lista de itens (sejam eles quais forem) com seus respectivos identificadores, uma vez que forem constantes. Ficou difícil ? calma… vamos lá…</p>
<p>Vamos supor que você tenha uma entidade (<code>classe</code>, <code>struct</code>, etc…) carro, e você tem um atributo chamado Combustivel. Você já sabe que seus tipos de combustíveis serão sempre: gasolina, álcool, flex ou diesel, e você quer armazenar esta constante em um lugar para não ter que ficar sempre trabalhando com string no seu código…</p>
<p>Neste caso, poderíamos resolver este cara, assim:</p>
<pre><code>public class Program
{
static void Main(string[] args)
{
//var carro = new Carro();
//carro.Marca = "Fiat";
//carro.Modelo = "Uno";
//carro.Combustivel = Combustivel.Alcool;
//Você sabia que essas duas formas de preencher um objeto
//são iguais ne ? provavelmente sim, mas não custa dizer..
var carro = new Carro()
{
Marca = "Fiat",
Modelo = "Uno",
Combustivel = Combustivel.Alcool
};
Console.ReadKey();
}
}
public struct Carro
{
public string Modelo { get; set; }
public string Marca { get; set; }
public Combustivel Combustivel { get; set; }
}
public enum Combustivel
{
Gasolina = 0,
Alcool = 1,
Flex = 2,
Diesel = 3
}
</code></pre>
<p>Bom, agora temos o atributo combustível na entidade carro e podemos armazená-lo em algum arquivo ou banco de dados utilizando o numero inteiro que está identificando cada tipo de combustível.</p>
<p>Aí você pode falar: tá, legal, <strike>valeu champs</strike> mas e se eu quiser usar a descrição do combustível para apresentar em algum lugar?</p>
<p>Se eu te falar que é só fazer assim: <code>carro.Combustivel.ToString();</code> você não acredita… pois é, por exemplo, ali na situação do carro, esta linha de código nos retornaria “Alcool”.</p>
<p>Mas calma, essa nossa conversa está bem didática, no seu dia a dia você pode passar por algumas <strike>tretas mais loucas</strike> dificuldades usando enum. A seguir veja a classe TruquesDicasEnum onde implemento 3 <strong>truques</strong> que podemos usar.</p>
<p>Nos métodos desta classe, utilizamos um recurso chamado <strong>“extension”</strong>, caso não tenha familiaridade com este recurso, ou queira aprender mais sobre ele, sugiro que leia este <a href="http://nilsonsrjunior.net/extensions-aumentando-a-produtividade/">post</a> que eu fiz.</p>
<p>Enfim, as classes:</p>
<pre><code>public static class TruquesDicasEnum
{
public static string GetDescription(this Enum source)
{
FieldInfo fi = source.GetType().GetField(source.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute), false);
if (attributes != null &amp;&amp; attributes.Length &gt; 0) return attributes[0].Description;
else return source.ToString();
}
public static Enum FindByDescription&lt;T&gt;(this string description)
{
FieldInfo[] fi = typeof(T).GetFields();
foreach (var item in fi)
{
var attributes =
(DescriptionAttribute[])item.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Any())
{
var field =
attributes.FirstOrDefault(x =&gt; x.Description.Equals(description));
if (field != null)
{
return (Enum)Enum.Parse(typeof(T), item.Name);
}
}
}
return null;
}
public static IList&lt;T&gt; EnumToList&lt;T&gt;(this IEnumerable dados)
{
return Enum.GetValues(typeof(T)).Cast&lt;T&gt;().ToList();
}
}
</code></pre>
<ul>
<li><strong>Truque 1: Alterando a descrição do enum</strong></li>
</ul>
<p>Vamos supor, que no nosso exemplo do combustível, queremos que a opção Alcool tenha acento quando formos utilizar a sua <code>string</code>, como já vimos anteriormente.</p>
<p>É bem fácil, basta decorarmos nossa opção Alcool com o atributo <strong>Description</strong>. Encontramos este atributo usando a biblioteca <code>System.ComponentModel.Description</code>. Veja o exemplo:</p>
<pre><code>public enum Combustivel
{
Gasolina = 0,
[System.ComponentModel.Description("Álcool")]
Alcool = 1,
Flex = 2,
Diesel = 3
}
</code></pre>
<p>Uma vez referenciada a biblioteca e adicionado o atributo, é só passarmos como parâmetro para ele, a nossa nova descrição, com acento.</p>
<p>Para exemplificarmos como iremos pegar essa nova descrição de maneira prática, vamos usar nosso primeiro método da classe de truques. O “<code>GetDescription()</code>”, que fica desta forma:</p>
<p><code>var novaDescricaoEnum = carro.Combustivel.GetDescription();</code></p>
<p>E como resultado teremos “Álcool”.</p>
<ul>
<li><strong>Truque 2: “Pegando” enum pela descrição</strong></li>
</ul>
<p>Certa vez eu precisava selecionar qual era a opção de um enum para pegar o seu identificador inteiro, e tudo que eu tinha era a Description (mencionada acima) do enum.</p>
<p>Após alguns fios de cabelo perdido e estudo sobre reflection, obtive o segundo método da classe de truques, “<code>FindByDescription&lt;T&gt;</code>”. Veja como poderíamos usar ele no nosso exemplo:</p>
<pre><code>string descEnum = "Álcool";
var enumPorDescricao = descEnum.FindByDescription&lt;Combustivel&gt;();
</code></pre>
<p>Viu só ? simples demais né… agora vamos ao último, mas não menos importante…</p>
<ul>
<li><strong>Truque 3: Transformando um enum em uma coleção</strong></li>
</ul>
<p>Imagine que você queira pegar todas as opções do nosso enum Combustível e retornar em uma coleção para preencher as options de um <code>&lt;select&gt;</code> da vida, por exemplo. Para fazermos isso, vamos ao terceiro e último método da nossa classe de truques, o “<code>EnumToList&lt;T&gt;</code>”.</p>
<pre><code>private IEnumerable&lt;Combustivel&gt; combustiveis;
public IEnumerable&lt;Combustivel&gt; Combustiveis
{
get { return combustiveis ?? (combustiveis.EnumToList&lt;Combustivel&gt;()); }
set { combustiveis = value; }
}
</code></pre>
<p>Neste caso a situação foi a seguinte: eu precisava de uma propriedade, onde toda vez que eu fosse recuperá-la e ela estivesse nula (por isso os dois sinais de interrogação - ??) , eu retornaria todas as opções do enum em uma coleção. Show né ??.</p>
<p>Espero muito que tenha te ajudado de alguma forma, nem que só um cadinho. Agradeço por ter lido até o fim, por enquanto é isso!.</p>
<p>Você pode baixar o código fonte deste post <a href="https://github.com/nilsonsrjunior/blog-projects/tree/master/TrabalhandoComEnums">aqui</a>.</p>
<p>Faça seu comentário, um grande abraço e até breve !!!</p>
</description>
<pubDate>Thu, 03 Dec 2015 20:25:00 -0200</pubDate>
<link>http://nilsonsrjunior.net/enums-dicas-e-truques</link>
<guid isPermaLink="true">http://nilsonsrjunior.net/enums-dicas-e-truques</guid>
<category>csharp</category>
</item>
<item>
<title>Yield ? É de comer ?</title>
<description><p>Primeira coisa…. não é de comer, mas não fique triste, você vai descobrir que é muito bom.</p>
<p>Desde a versão 2.0 do C#, este camarada está lá. Mas afinal, o que é <code>yield</code> e para que serve ?</p>
<p>O <code>yield</code> é um iterador, isto significa que ele te ajudar naqueles momentos em que precisa criar uma coleção/lista para determinado fim.</p>
<p>Sabe aquela hora em que você declara uma lista só para preencher um campo e retorná-la ? Tipo assim:</p>
<pre><code>public struct Pessoa
{
public string Nome { get; set; }
public string Email { get; set; }
}
public static IEnumerable&lt;string&gt; RetornaEmails(IEnumerable&lt;Pessoa&gt; pessoas)
{
List&lt;string&gt; lista = new List&lt;string&gt;();
foreach (Pessoa pessoa in pessoas)
{
if (!string.IsNullOrEmpty(pessoa.Email))
lista.Add(pessoa.Email);
}
return lista;
}
</code></pre>
<p>No exemplo acima, a lógica é: se a pessoa possuir e-mail, eu a adiciono na lista para retornar. Agora olha só como podemos resolver a mesma situação, utilizando yield:</p>
<pre><code>public struct Pessoa
{
public string Nome { get; set; }
public string Email { get; set; }
}
public static IEnumerable&lt;string&gt; RetornaEmails(IEnumerable&lt;Pessoa&gt; pessoas)
{
List&lt;string&gt; lista = new List&lt;string&gt;();
foreach (Pessoa pessoa in pessoas)
{
if (!string.IsNullOrEmpty(pessoa.Email))
lista.Add(pessoa.Email);
}
return lista;
}
public static IEnumerable&lt;string&gt; RetornaEmailsUsandoYield(IEnumerable&lt;Pessoa&gt; pessoas)
{
foreach (Pessoa pessoa in pessoas)
{
if (!string.IsNullOrEmpty(pessoa.Email))
yield return pessoa.Email;
}
yield break;
}
</code></pre>
<p>Viu só ? não precisamos mais criar aquela lista, pode parecer um recurso não tão atraente, mas venhamos e convenhamos, ficar declarando lista só para ter algo pra preencher e retornar é uma coisa que dá nos nervos trabalho.</p>
<p>E a performance disso, você pode estar se perguntando… bom, aqui vai um teste simples que eu fiz em um console application, para que você não fique em dúvidas:</p>
<pre><code>class Program
{
static void Main(string[] args)
{
var pessoa = new Pessoa();
var cronometro = new Stopwatch();
cronometro.Start();
IEnumerable&lt;string&gt; colecao = PopulaColecaoNormal(pessoa);
cronometro.Stop();
var tempoColecaoNormal = cronometro.Elapsed;
cronometro.Reset();
cronometro.Start();
IEnumerable&lt;string&gt; colecaoYield = PopulaColecaoYield(pessoa);
cronometro.Stop();
var tempoColecaoYield = cronometro.Elapsed;
Console.WriteLine("Tempo de execução para coleção: " + tempoColecaoNormal);
Console.Write(Environment.NewLine);
Console.WriteLine("Tempo de execução para coleção yield: " + tempoColecaoYield);
Console.ReadKey();
}
public struct Pessoa
{
public string Nome { get; set; }
public string Email { get; set; }
}
private static IEnumerable&lt;string&gt; PopulaColecaoNormal(Pessoa pessoa)
{
var lista = new List&lt;string&gt;();
if (string.IsNullOrEmpty(pessoa.Nome))
lista.Add("Nome é obrigatório");
if (string.IsNullOrEmpty(pessoa.Email))
lista.Add("Email é obrigatório");
return lista;
}
private static IEnumerable&lt;string&gt; PopulaColecaoYield(Pessoa pessoa)
{
if (string.IsNullOrEmpty(pessoa.Nome))
yield return "Nome é obrigatório";
if (string.IsNullOrEmpty(pessoa.Email))
yield return "Email é obrigatório";
yield break;
}
}
</code></pre>
<p>Como podem ver, nosso amigo yield se saiu vencedor na história. Espero que tenha conseguido te ajudar de alguma forma.</p>
<p>Você pode baixar o código fonte deste post <a href="https://github.com/nilsonsrjunior/blog-projects/tree/master/UtilizandoYield">aqui</a>.</p>
<p>Faça seu comentário, um grande abraço, e até breve !!!</p>
</description>
<pubDate>Thu, 03 Dec 2015 17:28:00 -0200</pubDate>
<link>http://nilsonsrjunior.net/yield-e-de-comer</link>
<guid isPermaLink="true">http://nilsonsrjunior.net/yield-e-de-comer</guid>
<category>csharp</category>
</item>
</channel>
</rss>