Essa valeu de tão simples.
Na necessidade de precisar limpar as tags HTML de uma string para apresenta-la em um local que não um browser ou componente que pudesse interpretá-lo, precisei construir uma rotina para a tarefa. Como de costume, programador pensa sempre na solução mais difícil. Mas depois de um pouco de preguiça saudável, não foi complicado decidir que através de uma simples Regular Expression o trabalho poderia ser feito facilmente. Antes mesmo de precisar queimar neurônios pensando em uma, resolvi garimpar no um pouco na Web. Em poucos segundos, o resultado era o código abaixo:
public string Strip(string text)
{
return Regex.Replace(text, @”<(.|\n)*?>”, string.Empty);
}
O autor da proeza é Ali Raza.
Bom proveito!
O LINQ, juntamente com as Lambda Expressions resolveram problemas que em versões anteriores do .NET Framework eram feitos através de Loops ou coisa parecida.
Um exemplo típico é quando desejamos obter um lista do IDs de uma lista tipada de objetos, por exemplo, Cliente ou Produto. Não tem jeito. É preciso um Loop for/while/foreach para capturar determinada lista.
Porém, a partir do .NET Framework 2.0 e o lançamento do Generics, trabalhos em listas passaram a ser bem mais simples. Neste caso, que faz a proeza é o método List.ConvertAll. O que ele faz é converter uma Lista (List) de um determinado tipo e um outra Lista cujo o tipo é informado.
Um exemplo de seu uso (da própria Microsoft) pode ser visto abaixo:
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
| using System;
using System.Drawing;
using System.Collections.Generic;
public class Example
{
public static void Main()
{
List
lpf = new List
();
lpf.Add(new PointF(27.8F, 32.62F));
lpf.Add(new PointF(99.3F, 147.273F));
lpf.Add(new PointF(7.5F, 1412.2F));
Console.WriteLine();
foreach( PointF p in lpf )
{
Console.WriteLine(p);
}
List
lp = lpf.ConvertAll(
new Converter
(PointFToPoint));
Console.WriteLine();
foreach( Point p in lp )
{
Console.WriteLine(p);
}
}
public static Point PointFToPoint(PointF pf)
{
return new Point(((int) pf.X), ((int) pf.Y));
}
}
/* O código de exemplo produz a seguinte saída:
{X=27.8, Y=32.62}
{X=99.3, Y=147.273}
{X=7.5, Y=1412.2}
{X=27,Y=32}
{X=99,Y=147}
{X=7,Y=1412}
*/ |
Porém, é possível dar exemplo “mais real”. Imagine que você tenha um classe Usuário e que ela tenha seus atributos tradicionais (ID, Nome, Idade, etc…). O código abaixo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // declara uma lista tipada da classe User
List Users = new List();
// adiciona alguns registros
Users.Add(new User(1, "User 1"));
Users.Add(new User(2, "User 2"));
Users.Add(new User(3, "User 3"));
// coleta uma lista tipada de int contendo os ids dos usuários com o método List.ConvertAll
List userIds = Users.ConvertAll(delegate(User user)
{
return user.ID;
});
// imprime no Console
foreach(int id in userIds)
{
Console.WriteLine(s);
} |
Note que o uso do List.ConvertAll exige o uso de um delegate, que no caso, está utilizando um método anônimo (ver referências).
Uma mão da roda (para quem não tem LINQ)!
Referências:
http://msdn.microsoft.com/en-us/library/0yw3tz5k%28VS.80%29.aspx
http://msdn.microsoft.com/en-us/library/73fe8cwf%28VS.85%29.aspx
http://pontonetpt.com/blogs/israelaece/archive/2005/05/23/P4746.aspx
Não é muito comum, mas o ADO.NET nos dá a possibilidade de através de uma consulta feita pelo objeto Command (ou DataAdapter), retornar mais de um ResultSet ou tabela do banco de dados.
Em um exemplo, veja o código abaixo
1
2
3
4
5
6
7
8
9
10
11
| string select = "select * from Categories; select * from Customers";
SqlCommand command = new SqlCommand ( select, conn );
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = command;
DataSet ds = new DataSet();
adapter.Fill(ds);
foreach(DataTable table in ds.Tables)
{
Console.WriteLine(table.TableName);
} |
Naturalmente, o comando sql podia chamar uma stored procedure existente no bando de dados, o que daria o mesmo efeito. Com isso, o DataSet ds teria como resultado 2 objetos DataTable preenchidos, Categories e Customers, resultado do comando sql disparado.
Mas, como conseguir esse efeito com um DataReader, sendo que comumente sempre esperamos um ResultSet, iterando através dos campos diretamente pelo índice ou nome deste? Simples! A interface IDataReader possui o método NextResult que permite pular para o próximo ResultSet, caso este exista. O NextResult retorna um bool, que da mesma forma que o método Read, retorna true se houver mais resultados e automaticamente “move o cursor” para o próximo ResultSet. O exemplo abaixo demonstra o funcionamento:
1
2
3
4
5
6
7
8
9
10
11
12
| string select = "select * from Categories; select * from customers";
SqlCommand command = new SqlCommand ( select, conn );
conn.Open ();
SqlDataReader reader = command.ExecuteReader ();
do
{
while ( reader.Read () )
{
Console.WriteLine ( "{0}\t\t{1}", reader[0], reader[1] );
}
}while ( reader.NextResult () ); |
Referências:
http://stackoverflow.com/
Dica publicada pelo pessoal da BufaloInfo.
Não há ainda, nas classes do framework, um meio de obter o tamanho total de um diretório. Por isso o tamanho total de um diretório deve ser obtido pela soma do tamanho de seus arquivos e diretórios, da seguinte forma :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| public static long Size(System.IO.DirectoryInfo dirInfo)
{
long total = 0;
// Obtem o tamanho total dos arquivos no diretório
foreach(System.IO.FileInfo file in dirInfo.GetFiles())
total += file.Length;
// Obtem o tamanho total dos sub-diretórios da pasta
foreach(System.IO.DirectoryInfo dir in dirInfo.GetDirectories())
total += Size(dir);
return total;
} |
É interessante observar que esta função é recursiva : Ao encontrar uma pasta a função chama a si mesma para poder calcular o tamanho da pasta e desta forma somar ao tamanho total.
No link abaixo há uma explicação mais detalha sobre Recursividade e os cuidados a considerar em seu uso:
http://pt.wikipedia.org/wiki/Recursividade