Finalmente, vamos agora para a implementação do pattern Repository usando o Entity Framework. Na Parte 2 nós criamos a interface IRepository e também o ContextManager, um helper para a criação do contexto. A implementação será chamada EFRepository e definirá, através de generics, dois tipos, sendo que um será o tipo do objeto que será persistido e o outro será o tipo (classe) do contexto do Entity Framework. Vamos para o código!

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Data;
   4: using System.Data.Metadata.Edm;
   5: using System.Data.Objects;
   6: using System.Data.Objects.DataClasses;
   7: using System.Linq;
   8: using System.Linq.Expressions;
   9: using Net.Bragil.Data.Context;
  10:  
  11: namespace Net.Bragil.Data.Repository
  12: {
  13:     /// <summary>
  14:     /// Repositório genérico para o Entity Framework com as operações mais comuns de persistência, como inserção, atualização,
  15:     /// exclusão e seleção.
  16:     /// </summary>
  17:     /// <typeparam name="E">Tipo do objeto a ser persistido</typeparam>
  18:     /// <typeparam name="C">Tipo do contexto</typeparam>
  19:     public class EFRepository<E, C> : IRepository<E, C>, IDisposable
  20:         where E : EntityObject
  21:         where C : ObjectContext
  22:     {
  23:         /// <summary>
  24:         /// Contexto do Entity Framework
  25:         /// </summary>
  26:         private C context;
  27:  
  28:         /// <summary>
  29:         /// Contexto do Entity Framework
  30:         /// </summary>
  31:         public C Context
  32:         {
  33:             get { return context; }
  34:             set { context = value; }
  35:         }
  36:  
  37:         /// <summary>
  38:         /// Retorna o nome do EntitySet do objeto persistente
  39:         /// </summary>
  40:         private string entitySetName;
  41:  
  42:         /// <summary>
  43:         /// Retorna o nome do EntitySet do objeto persistente
  44:         /// </summary>
  45:         protected string EntitySetName
  46:         {
  47:             get
  48:             {
  49:                 if (String.IsNullOrEmpty(entitySetName))
  50:                 {
  51:                     entitySetName = GetEntitySetName(typeof(E).Name);
  52:                 }
  53:                 return entitySetName;
  54:             }
  55:         }
  56:  
  57:         /// <summary>
  58:         /// Construtor padrão, sem argumentos. Obtém o contexto do Entity Framework usando o ContextManager.
  59:         /// </summary>
  60:         public EFRepository()
  61:         {
  62:             // Obtém o contexto
  63:             this.context = ContextManager.GetContext<C>();
  64:         }
  65:  
  66:         /// <summary>
  67:         /// Insere um novo objeto persistente
  68:         /// </summary>
  69:         /// <param name="entity">Objeto a ser inserido</param>
  70:         public void Insert(E entity)
  71:         {
  72:             context.AddObject(EntitySetName, entity);
  73:         }
  74:  
  75:         /// <summary>
  76:         /// Atualiza um objeto existente.
  77:         /// </summary>
  78:         /// <param name="entity">Objeto persistente</param>
  79:         public virtual void Update(E entity)
  80:         {
  81:             EntityKey key;
  82:             object originalItem;
  83:             if (entity.EntityKey == null)
  84:                 // Obtém o entity key do objeto que será atualizado
  85:                 key = Context.CreateEntityKey(EntitySetName, entity);
  86:             else
  87:                 key = entity.EntityKey;
  88:             try
  89:             {
  90:                 // Obtém o objeto original
  91:                 if (Context.TryGetObjectByKey(key, out originalItem))
  92:                 {
  93:                     if (originalItem is EntityObject &&
  94:                         ((EntityObject)originalItem).EntityState != EntityState.Added)
  95:                     {
  96:                         // Autaliza o objeto
  97:                         context.ApplyPropertyChanges(key.EntitySetName, entity);
  98:                     }
  99:                 }
 100:             }
 101:             catch (Exception ex)
 102:             {
 103:                 throw ex;
 104:             }
 105:  
 106:         }
 107:  
 108:         /// <summary>
 109:         /// Exclui um objeto persistente
 110:         /// </summary>
 111:         /// <param name="entity">Objeto persistente que será excluído</param>
 112:         public void Delete(E entity)
 113:         {
 114:             context.DeleteObject(entity);
 115:         }
 116:  
 117:         /// <summary>
 118:         /// Retorna um objeto que satisfaça a cláusula passada como parâmetro.
 119:         /// </summary>
 120:         /// <param name="expression">Expressão Lambda da cláusula WHERE</param>
 121:         public E SelectOne(Expression<Func<E, bool>> where)
 122:         {
 123:             return context.CreateQuery<E>(EntitySetName).Where(where).FirstOrDefault();
 124:         }
 125:  
 126:         /// <summary>
 127:         /// Salva as alterações no banco de dados.
 128:         /// </summary>
 129:         public void SaveChanges()
 130:         {
 131:             context.SaveChanges();
 132:         }
 133:  
 134:         /// <summary>
 135:         /// Retorna todos os objetos persistentes.
 136:         /// </summary>
 137:         /// <returns>Coleção com todos os objetos</returns>
 138:         public List<E> SelectAll()
 139:         {
 140:             return context.CreateQuery<E>(EntitySetName).ToList();
 141:         }
 142:  
 143:         /// <summary>
 144:         /// Retorna um IQueryable com todos os objetos
 145:         /// </summary>
 146:         /// <returns>IQueryable com todos os objetos</returns>
 147:         public IQueryable<E> QueryAll()
 148:         {
 149:             return context.CreateQuery<E>(EntitySetName).AsQueryable<E>();
 150:         }
 151:  
 152:         /// <summary>
 153:         /// Retorna todos os objetos usando paginação.
 154:         /// </summary>
 155:         /// <param name="maximumRows">Quantidade de objetos por página</param>
 156:         /// <param name="startRowIndex">Linha a partir do qual os objetos serão retornados</param>
 157:         /// <returns>Coleção com todos os objetos</returns>
 158:         public List<E> SelectAll(int maximumRows, int startRowIndex)
 159:         {
 160:             return context.CreateQuery<E>(EntitySetName).Skip<E>(startRowIndex).Take(maximumRows).ToList();
 161:         }
 162:  
 163:         /// <summary>
 164:         /// Retorna um IQueryable com todos os objetos usando paginação
 165:         /// </summary>
 166:         /// <param name="maximumRows">Quantidade de objetos por página</param>
 167:         /// <param name="startRowIndex">Linha a partir do qual os objetos serão retornados</param>
 168:         /// <returns>IQueryable com todos os objetos</returns>
 169:         public IQueryable<E> QueryAll(int maximumRows, int startRowIndex)
 170:         {
 171:             return context.CreateQuery<E>(EntitySetName).Skip<E>(startRowIndex).Take(maximumRows);
 172:         }
 173:  
 174:         /// <summary>
 175:         /// Retorna todos os objetos que satisfaçam a cláusula passada
 176:         /// </summary>
 177:         /// <param name="where">Expressão Lambda da cláusula WHERE</param>
 178:         public List<E> SelectWhere(Expression<Func<E, bool>> where)
 179:         {
 180:             return context.CreateQuery<E>(EntitySetName).Where(where).ToList();
 181:         }
 182:  
 183:         /// <summary>
 184:         /// Retorna todos os objetos que satisfaçam a cláusula passada, usando paginação
 185:         /// </summary>
 186:         /// <param name="where">Expressão Lambda da cláusula WHERE</param>
 187:         /// <param name="maximumRows">Quantidade de objetos por página</param>
 188:         /// <param name="startRowIndex">Linha a partir do qual os objetos serão retornados</param>
 189:         public List<E> SelectWhere(Expression<Func<E, bool>> where, int maximumRows, int startRowIndex)
 190:         {
 191:             return context.CreateQuery<E>(EntitySetName).Where(where)
 192:                           .Skip<E>(startRowIndex).Take(maximumRows).ToList();
 193:         }
 194:  
 195:         /// <summary>
 196:         /// Retorna o número de objetos
 197:         /// </summary>
 198:         /// <remarks>Para ser usado na configuração da paginação</remarks>
 199:         public int GetCount()
 200:         {
 201:             return context.CreateQuery<E>(EntitySetName).Count();
 202:         }
 203:  
 204:         /// <summary>
 205:         /// Retorna o número de objetos que satisfaçam a cláusula passada
 206:         /// </summary>
 207:         /// <remarks>Para ser usado na configuração da paginação</remarks>
 208:         public int GetCount(Expression<Func<E, bool>> where)
 209:         {
 210:             return context.CreateQuery<E>(EntitySetName).Where(where).Count();
 211:         }
 212:  
 213:         /// <summary>
 214:         /// Libera os recursos do Entity Framework.
 215:         /// </summary>
 216:         public void Dispose()
 217:         {
 218:             if (context != null)
 219:                 context.Dispose();
 220:         }
 221:  
 222:         /// <summary>
 223:         /// Retorna o nome do EntitySet, possibilitando a criação de métodos genéricos.
 224:         /// </summary>
 225:         /// <param name="entityTypeName">String com o nome do tipo</param>
 226:         /// <returns>String contendo o EntitySet</returns>
 227:         private string GetEntitySetName(string entityTypeName)
 228:         {
 229:             var container = context.MetadataWorkspace.GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace);
 230:             string entitySetName = (from meta in container.BaseEntitySets
 231:                                     where meta.ElementType.Name == entityTypeName
 232:                                     select meta.Name).FirstOrDefault();
 233:             return entitySetName;
 234:         }
 235:  
 236:     }
 237:  
 238:  
 239: }

Na primeira parte deste artigo, criamos o banco de dados e geramos o contexto do Entity Framework para o modelo. Agora, vamos começar a definir o componente para o pattern Repository. Segue uma lista dos requisitos para o componente:

Deverá oferecer a possibilidade de trabalhar independente dos tipos envolvidos

Ou seja, poderemos usar o mesmo componente para persistir qualquer objeto, independente do contexto usado. Isso é facilmente conseguido através do uso de Generic Types, sendo possível parametrizar os tipos que serão trabalhados durante as operações de persistência.

Deverá simplificar o desenvolvimento para as rotinas básicas de persistência

O objetivo será tornar o desenvolvimento o mais simples possível, procurando encapsular todo o “trabalho sujo” e criar uma interface limpa e amigável para o programador.

Baseado nas especificações acima, segue a Interface do componente Repository para o Entity Framework:

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Linq.Expressions;
   5:  
   6: namespace Net.Bragil.Data.Repository
   7: {
   8:     /// <summary>
   9:     /// Interface para a implementação do padrão Repository usando o Entity Framework.
  10:     /// </summary>
  11:     /// <typeparam name="E">Tipo do objeto persistente</typeparam>
  12:     /// <typeparam name="C">Tipo do contexto do Entity Framework</typeparam>
  13:     public interface IRepository<E, C>
  14:     {
  15:         /// <summary>
  16:         /// Contexto do Entity Framework
  17:         /// </summary>
  18:         C Context { get; set; }
  19:  
  20:         /// <summary>
  21:         /// Inserção
  22:         /// </summary>
  23:         void Insert(E entity);
  24:  
  25:         /// <summary>
  26:         /// Atualização
  27:         /// </summary>
  28:         void Update(E entity);
  29:  
  30:         /// <summary>
  31:         /// Exclusão
  32:         /// </summary>
  33:         void Delete(E entity);
  34:  
  35:         /// <summary>
  36:         /// Retorna o objeto que satisfaça a cláusula passada como argumento (cláusula WHERE)
  37:         /// </summary>
  38:         E SelectOne(Expression<Func<E, bool>> where);
  39:  
  40:         /// <summary>
  41:         /// Retorna todos os objetos de um tipo
  42:         /// </summary>
  43:         List<E> SelectAll();
  44:  
  45:         /// <summary>
  46:         /// Retorna os objetos usando paginação
  47:         /// </summary>
  48:         List<E> SelectAll(int maximumRows, int startRowIndex);
  49:  
  50:         /// <summary>
  51:         /// Retorna todos os objetos que satisfaçam a cláusula passada
  52:         /// </summary>
  53:         /// <param name="where">Cláusula WHERE</param>
  54:         List<E> SelectWhere(Expression<Func<E, bool>> where);
  55:  
  56:         /// <summary>
  57:         /// Retorna os objetos que satisfaçam a cláusula passada, usando paginação
  58:         /// </summary>
  59:         /// <param name="where">Cláusula WHERE</param>
  60:         List<E> SelectWhere(Expression<Func<E, bool>> where, int maximumRows, int startRowIndex);
  61:  
  62:         /// <summary>
  63:         /// Retorna um objeto IQueryable, possibilitando formar queries usando expressões Lambda
  64:         /// </summary>
  65:         IQueryable<E> QueryAll();
  66:  
  67:         /// <summary>
  68:         /// Retorna um IQueryable com os objetos usando paginação
  69:         /// </summary>
  70:         IQueryable<E> QueryAll(int maximumRows, int startRowIndex);
  71:  
  72:         /// <summary>
  73:         /// Retorna a quantidade de objetos persistentes.
  74:         /// </summary>
  75:         int GetCount();
  76:  
  77:         /// <summary>
  78:         /// Retorna a quantidade de objetos persistentes que satisfaçam a cláusula WHERE
  79:         /// </summary>
  80:         int GetCount(Expression<Func<E, bool>> where);
  81:     }
  82: }

Como você pode ver, o componente oferecerá a maioria dos recursos de persistência, de uma forma muito mais amigável do que usando o Entity Framework diretamente.

Foi necessário também a criação de uma classe auxiliar para instanciação do contexto do Entity Framework usando a estratégia “One-Per-Request”, ou seja, é criada apenas uma instância do contexto por requisição. O objeto do contexto é armazenado em HttpContext.Current.Items, de modo que as chamadas subsequentes dentro da mesma requisição retornam o contexto anteriormente instanciado e armazenado na requisição. Segue o código:

   1: using System.Web;
   2: using System.Data.Objects;
   3:  
   4: namespace Net.Bragil.Data.Context
   5: {
   6:     /// <summary>
   7:     /// Classe gerenciadora do contexto do Entity Framework. Utiliza generics para determinar em tempo de execução o 
   8:     /// tipo do contexto e Reflection para instanciar o tipo genérico. Armazena o contexto no HttpContext, de modo que 
   9:     /// não seja necessário instanciar o contexto nas próximas chamadas dentro da requisição web.
  10:     /// </summary>
  11:     public sealed class ContextManager
  12:     {
  13:         /// <summary>
  14:         /// Construtor privado, não será possível instanciar a classe usando new
  15:         /// </summary>
  16:         private ContextManager()
  17:         {
  18:         }
  19:  
  20:         /// <summary>
  21:         /// Obtém o contexto do Entity Framework usando generics.
  22:         /// </summary>
  23:         /// <typeparam name="T">Tipo do contexto do Entity Framework (deve herdar de ObjectContext)</typeparam>
  24:         /// <returns>Contexto do Entity Framework</returns>
  25:         public static T GetContext<T>()
  26:             where T: ObjectContext
  27:         {
  28:             string ocKey = "ocm_" + HttpContext.Current.GetHashCode().ToString("x");
  29:             if (HttpContext.Current != null)
  30:             {
  31:                 if (!HttpContext.Current.Items.Contains(ocKey))
  32:                 {
  33:                     // Instancia o contexto através de Reflection
  34:                     T ctx = typeof(T).GetConstructor(System.Type.EmptyTypes).Invoke(System.Type.EmptyTypes) as T;
  35:                     // Armazena na requisição
  36:                     HttpContext.Current.Items.Add(ocKey, ctx);
  37:                 }
  38:                 return HttpContext.Current.Items[ocKey] as T;
  39:             }
  40:             else
  41:                 // Caso a aplicação não seja web, instancia e retorna o contexto.
  42:                 return typeof(T).GetConstructor(System.Type.EmptyTypes).Invoke(System.Type.EmptyTypes) as T;
  43:             
  44:         }
  45:  
  46:     }
  47: }

Já estamos quase lá! No próximo artigo vamos desenvolver a implementação da classe EFRepository.


Admin posted on August 19, 2009 05:11

Os arquivos de configuração .INI há um bom tempo foram substituídos no .Net pelos arquivos XML, muito mais flexíveis e padronizados. Entretanto, quando trabalhamos com sistemas legados, seja para fazer integrações, migrações ou o que quer que seja, acabamos nos deparando com os saudosos arquivos .INI. Ao invés de criar rotinas caseiras para trabalhar com estes arquivos, que tal uma biblioteca em C# que cumpra esse papel com louvor? A biblioteca Nini faz isto e muito mais: além dos arquivos .INI, ela abstrai o acesso a arquivos de configuração XML, .Net Config, Registry e argumentos de linha de comando. O site do projeto não possui nada, apenas os links para poder baixar, mas a documentação vem junto com o arquivo baixado.

Segue um exemplo do próprio manual da Nini:

; MyApp.ini
[Logging]
File Name = MyApp.log
MessageColumns = 5
MaxFileSize = 40000000000000

   1: // Usando C#
   2: using Nini.Config;
   3: IConfigSource source = new IniConfigSource("MyApp.ini");
   4:  
   5: string fileName = source.Configs["Logging"].Get("File Name");
   6: int columns = source.Configs["Logging"].GetInt("MessageColumns");
   7: long fileSize = source.Configs["Logging"].GetLong("MaxFileSize");
   1: 'E usando VB.Net
   2: Imports Nini.Config
   3:  
   4: Dim source As New IniConfigSource("MyApp.ini")
   5:  
   6: Dim fileName As String = source.Configs("Logging").Get("File Name")
   7: Dim columns As Integer = source.Configs("Logging").GetInt("MessageColumns")
   8: Dim fileSize As Long = source.Configs("Logging").GetLong("MaxFileSize")

Posted in: .Net , C#  Tags: , , ,

Neste post vou apresentar um aplicativo para Windows Mobile 6 que recebe como entrada o valor do litro do álcool, da gasolina e exibe uma mensagem dizendo qual dos dois é mais vantajoso abastecer, bastante útil quando o seu veículo é flex. Faça o download do código fonte do projeto: AlcoolGasolina.zip (56,97 kb). Caso você queira apenas o .cab do aplicativo para instalar em seu smartphone, ele está na pasta AlcoolGasolinaSetup/Release.

Requisitos:

O código é bem simples, o valor do litro do álcool é dividido pelo valor do litro da gasolina, se o resultado for maior ou igual a 0,7 compensa abastecer com gasolina, caso contrário, abasteça com álcool.

   1:  using System;
   2:  using System.Text;
   3:  using System.Windows.Forms;
   4:   
   5:  namespace AlcoolGasolina
   6:  {
   7:      public partial class frmPrincipal : Form
   8:      {
   9:          public frmPrincipal()
  10:          {
  11:              InitializeComponent();
  12:          }
  13:   
  14:          /// <summary>
  15:          /// Método de validação da entrada. Considera inválidos strings vazias e 
  16:          /// valores menores ou iguais a zero.
  17:          /// </summary>
  18:          /// <param name="valor">O valor de entrada, formato string</param>
  19:          /// <returns>True para válido, False para inválido.</returns>
  20:          private bool isValid(string valor)
  21:          {
  22:              // Não deve ser uma string vazia ou nula
  23:              if (String.IsNullOrEmpty(valor))
  24:                  return false;
  25:              try
  26:              {
  27:                  // deve ser um valor numérico válido
  28:                  double num = Convert.ToDouble(valor);
  29:   
  30:                  // não deve ser menor ou igual a zero
  31:                  if (num > 0)
  32:                      return true;
  33:                  else
  34:                      return false;
  35:              }
  36:              catch (Exception)
  37:              {
  38:                  return false;
  39:              }
  40:          }
  41:   
  42:          /// <summary>
  43:          /// Verifica se os valores digitados são válidos e, em caso positivo, 
  44:          /// faz o cálculo e apresenta a mensagem para o usuário informando
  45:          /// qual é mais viável abastecer, álcool ou gasolina. Se os valores 
  46:          /// não forem válidos para o cálculo, será exibida uma mensagem de 
  47:          /// alerta, informando que os valores de entrada são inválidos.
  48:          /// </summary>
  49:          /// <param name="sender"></param>
  50:          /// <param name="e"></param>
  51:          private void btnCalcular_Click(object sender, EventArgs e)
  52:          {
  53:              if (isValid(txtAlcool.Text.Trim()) && isValid(txtGasolina.Text.Trim()))
  54:              {
  55:                  double alcool = Convert.ToDouble(txtAlcool.Text.Trim());
  56:                  double gasolina = Convert.ToDouble(txtGasolina.Text.Trim());
  57:   
  58:                  double resultado = alcool / gasolina;
  59:                  if (resultado >= 0.7)
  60:                      lblResultado.Text = "Abasteça com Gasolina";
  61:                  else
  62:                      lblResultado.Text = "Abasteça com Álcool";
  63:              }
  64:              else
  65:              {
  66:                  MessageBox.Show("Valores de entrada inválidos.", 
  67:                                  "Erro", 
  68:                                  MessageBoxButtons.OK, 
  69:                                  MessageBoxIcon.Exclamation, 
  70:                                  MessageBoxDefaultButton.Button1);
  71:              }
  72:              txtAlcool.Text = string.Empty;
  73:              txtGasolina.Text = string.Empty;
  74:          }
  75:   
  76:          /// <summary>
  77:          /// Fecha a aplicação.
  78:          /// </summary>
  79:          private void mnuSair_Click(object sender, EventArgs e)
  80:          {
  81:              Application.Exit();
  82:          }
  83:   
  84:          /// <summary>
  85:          /// Menu "Sobre...", exibe uma mensagem com o nome da aplicação, 
  86:          /// nome do autor e endereço do blog do autor.
  87:          /// </summary>
  88:          private void mnuSobre_Click(object sender, EventArgs e)
  89:          {
  90:              StringBuilder mensagem = new StringBuilder("Álcool ou Gasolina\n\n");
  91:              mensagem.Append("Por Rogério Bragil\n\nBlog do Bragil - www.bragil.net");
  92:              MessageBox.Show(mensagem.ToString(), 
  93:                              "Sobre", 
  94:                              MessageBoxButtons.OK, 
  95:                              MessageBoxIcon.None, 
  96:                              MessageBoxDefaultButton.Button1);
  97:          }
  98:      }
  99:  }

 

 


Posted in: .Net , C# , Windows Mobile  Tags: , ,
Admin posted on August 6, 2009 10:12

Precisa fazer parsing de HTML em .Net? Experimente o HTML Agility Pack. Com ele você pode facilmente ler uma página HTML e acessar os seus elementos através de expressões XPath, ou então percorrer os nós da estrutura de árvore da página HTML. Vou mostrar aqui um exemplo prático, uma pequena aplicação Windows Forms que, dada uma URL, retorna todos os elementos a (links) existentes na página. Você pode alterar o programa para poder extrair conteúdo de sites, efetuar buscas, etc.

Acesse o site do HTML Agility Pack e faça o download do código fonte. Descompacte, abra o projeto no Visual Studio (2005 ou superior) e compile o projeto HtmlAgilityPack, que deverá gerar a dll com o mesmo nome na pasta bin do projeto. Com a dll criada, feche a solução atual (com o código do HTML Agility Pack) e crie um novo projeto Windows Application usando a linguagem C#. Adicione a referência para a dll do HTML Agility Pack, criada anteriormente. Adicione os seguintes controles no form:

  • TextBox, ID "txtUrl", onde será digitada a URL.
  • Button, ID "btnBusca", ao clicar esse botão, vai buscar a URL e processar.
  • ListBox, ID "lsbResultado", exibir os links encontrados na página.

 Agora, vamos para o código:

   1:  using System;
   2:  using HtmlAgilityPack;
   3:  using System.Windows.Forms;
   4:   
   5:  namespace PegaLinks
   6:  {
   7:      public partial class Form1 : Form
   8:      {
   9:          public Form1()
  10:          {
  11:              InitializeComponent();
  12:          }
  13:   
  14:          private void btnBusca_Click(object sender, EventArgs e)
  15:          {
  16:              try 
  17:              {
  18:                  HtmlWeb web = new HtmlWeb();
  19:                  // O método Load da classe HtmlWeb busca a página HTML e faz o parsing, atribuindo a
  20:                  // árvore do DOM (document object model) gerada ao objeto HtmlDocument
  21:                  HtmlAgilityPack.HtmlDocument doc = web.Load(@txtUrl.Text.Trim());
  22:                  
  23:                  // Aqui pegamos apenas o que interessa, os links (tags <a>), usando XPath
  24:                  HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes("/html/body//a");
  25:                  if (nodes != null)
  26:                  {
  27:                      // Percorremos a coleção dos nós encontrados (elementos <a>) e pegamos apenas o 
  28:                      // atributo href e o inner text de cada nó.
  29:                      foreach (HtmlNode node in nodes)
  30:                      {
  31:                          HtmlAttribute att = node.Attributes["href"];
  32:                          // Colocamos cada elemento no ListBox
  33:                          lsbResultado.Items.Add(node.InnerText + "  (" + att.Value + ")");
  34:                      }
  35:                  }
  36:                  else
  37:                  {
  38:                      MessageBox.Show("Nenhum link encontrado");
  39:                  }
  40:              }
  41:              catch (Exception ex)
  42:              {
  43:                  MessageBox.Show(ex.Message);
  44:              }   
  45:          }
  46:      }
  47:  }

 

Com poucas linhas você tem o que precisa: a informação limpinha. Sem precisar mexer com complexas expressões regulares ou parsing manual de strings... Tudo rápido e fácil! Não se esqueça de associar o evento Click do botão com o método btnBusca_Click.


Posted in: C# , .Net  Tags: , , , ,
Admin posted on September 29, 2008 07:09

Essa eu encontrei no Seven Library, uma rotina em C# para transformar valores decimais em sua representação por extenso em português do Brasil, usando reais como moeda. Algo bastante útil, difícil de encontrar pronto e meio chato de desenvolver. Segue o código:

   1:  using System;
   2:  using System.Collections;
   3:  using System.Text;
   4:   
   5:  namespace Teste
   6:  {
   7:   
   8:      public class NumeroPorExtenso
   9:      {
  10:   
  11:          private ArrayList numeroLista;
  12:   
  13:          private Int32 num;
  14:   
  15:          //array de 2 linhas e 14 colunas[2][14]
  16:          private static readonly String[,] qualificadores = new String[,] {
  17:  //                {"milésimo de real","milésimos de real"},//[0][0] e [0][1]
  18:                  {"centavo", "centavos"},//[1][0] e [1][1]
  19:                  {"", ""},//[2][0],[2][1]
  20:                  {"mil", "mil"},
  21:                  {"milhão", "milhões"},
  22:                  {"bilhão", "bilhões"},
  23:                  {"trilhão", "trilhões"},
  24:                  {"quatrilhão", "quatrilhões"},
  25:                  {"quintilhão", "quintilhões"},
  26:                  {"sextilhão", "sextilhões"},
  27:                  {"setilhão", "setilhões"},
  28:                  {"octilhão","octilhões"},
  29:                  {"nonilhão","nonilhões"},
  30:                  {"decilhão","decilhões"}
  31:                  };
  32:   
  33:          private static readonly String[,] numeros = new String[,] {
  34:                  {"zero", "um", "dois", "três", "quatro",
  35:                   "cinco", "seis", "sete", "oito", "nove",
  36:                   "dez","onze", "doze", "treze", "quatorze",
  37:                   "quinze", "dezesseis", "dezessete", "dezoito", "dezenove"},
  38:                  {"vinte", "trinta", "quarenta", "cinqüenta", "sessenta",
  39:                   "setenta", "oitenta", "noventa",null,null,null,null,null,null,null,null,null,null,null,null},
  40:                  {"cem", "cento",
  41:                   "duzentos", "trezentos", "quatrocentos", "quinhentos", "seiscentos",
  42:                   "setecentos", "oitocentos", "novecentos",null,null,null,null,null,null,null,null,null,null}
  43:                  };
  44:   
  45:          public NumeroPorExtenso() {
  46:              numeroLista = new ArrayList();
  47:          }
  48:   
  49:          public NumeroPorExtenso(Decimal dec) {
  50:              numeroLista = new ArrayList();
  51:              SetNumero(dec);
  52:          }
  53:   
  54:          public void SetNumero(Decimal dec) {
  55:              dec = Decimal.Round(dec,2);
  56:              dec = dec * 100;
  57:              num = Convert.ToInt32(dec);
  58:   
  59:              numeroLista.Clear();
  60:              if (num == 0)  {
  61:                  numeroLista.Add(0);
  62:                  numeroLista.Add(0);
  63:              } else {
  64:                  AddRemainder(100);
  65:   
  66:                  while (num != 0) {
  67:                      AddRemainder(1000);
  68:                  }
  69:   
  70:              }
  71:   
  72:          }
  73:   
  74:          private void AddRemainder(Int32 divisor) {
  75:              Int32 div = num / divisor;
  76:              Int32 mod = num % divisor;
  77:   
  78:              Int32[] newNum = new Int32[] {div,mod};
  79:   
  80:              numeroLista.Add(mod);
  81:   
  82:              num = div;
  83:          }
  84:   
  85:          private bool TemMaisGrupos(Int32 ps) {
  86:              while (ps > 0) {
  87:                  if ((Int32) numeroLista[ps] != 00 && !TemMaisGrupos(ps -1))
  88:                      return true;
  89:                  ps--;
  90:              }
  91:              return true;
  92:          }
  93:   
  94:          private bool EhPrimeiroGrupoUm() {
  95:              if ((Int32) numeroLista[numeroLista.Count-1] == 1)
  96:                  return true;
  97:              else
  98:                  return false;
  99:          }
 100:   
 101:          private bool EhUltimoGrupo(Int32 ps) {
 102:              return((ps > 0) && ((Int32) numeroLista[ps] != 0) || !TemMaisGrupos(ps - 1));
 103:          }
 104:   
 105:          private bool EhGrupoZero(Int32 ps) {
 106:              if (ps <= 0 || ps >= numeroLista.Count)
 107:                  return true;
 108:              return ((Int32) numeroLista[ps] == 0);
 109:          }
 110:   
 111:          private bool EhUnicoGrupo() {
 112:              if (numeroLista.Count <= 3)
 113:                  return false;
 114:   
 115:              if (!EhGrupoZero(1) && !EhGrupoZero(2))
 116:                  return false;
 117:   
 118:              bool hasOne = false;
 119:   
 120:              for (Int32 i=3; i < numeroLista.Count; i++) {
 121:                  if ((Int32) numeroLista[i] != 0) {
 122:                      if (hasOne)
 123:                          return false;
 124:                      hasOne = true;
 125:                  }
 126:              }
 127:              return true;
 128:          }
 129:   
 130:          private String NumToString(Int32 numero,Int32 escala) {
 131:              Int32 unidade = (numero % 10);
 132:              Int32 dezena = (numero % 100);
 133:              Int32 centena = (numero / 100);
 134:   
 135:              StringBuilder buf = new StringBuilder();
 136:   
 137:              if (numero != 0) {
 138:                  if (centena != 0) {
 139:                      if (dezena == 0 && centena == 1) {
 140:                          buf.Append(numeros[2,0]);
 141:                      } else {
 142:                          buf.Append(numeros[2,centena]);
 143:                      }
 144:                  }
 145:   
 146:                  if (buf.Length > 0 && dezena != 0) {
 147:                      buf.Append(" e ");
 148:                  }
 149:   
 150:                  if (dezena > 19) {
 151:                      dezena = dezena / 10;
 152:                      buf.Append(numeros[1,dezena-2]);
 153:                      if (unidade != 0) {
 154:                          buf.Append(" e ");
 155:                          buf.Append(numeros[0,unidade]);
 156:                      }
 157:                  } else if (centena == 0 || dezena != 0) {
 158:                      buf.Append(numeros[0,dezena]);
 159:                  }
 160:   
 161:                  buf.Append(" ");
 162:   
 163:                  if (numero == 1) {
 164:                      buf.Append(qualificadores[escala,0]);
 165:                  } else {
 166:                      buf.Append(qualificadores[escala,1]);
 167:                  }
 168:   
 169:              }
 170:              return buf.ToString();
 171:          }
 172:   
 173:          public String ToString() {
 174:              StringBuilder buf = new StringBuilder();
 175:   
 176:              Int32 numero = (Int32) numeroLista[0];
 177:              Int32 count;
 178:              for (count = numeroLista.Count -1; count > 0; count--) {
 179:                  if (buf.Length > 0 &&  !EhGrupoZero(count)) {
 180:                      buf.Append(" e ");
 181:                  }
 182:                  buf.Append(NumToString((Int32) numeroLista[count],count));
 183:              }
 184:   
 185:              if (buf.Length > 0) {
 186:   
 187:                  while (buf.ToString().EndsWith(" "))
 188:                      buf.Length = buf.Length -1;
 189:   
 190:                  if (EhUnicoGrupo()) {
 191:                      buf.Append(" de ");
 192:                  }
 193:   
 194:                  if (EhPrimeiroGrupoUm()) {
 195:                      buf.Insert(0,"h");
 196:                  }
 197:   
 198:                  if (numeroLista.Count == 2 && ((Int32) numeroLista[1] == 1)) {
 199:                      buf.Append(" real");
 200:                  } else {
 201:                      buf.Append(" reais");
 202:                  }
 203:   
 204:                  if ((Int32) numeroLista[0] != 0) {
 205:                      buf.Append(" e ");
 206:                  }
 207:              }
 208:   
 209:              if ((Int32) numeroLista[0] != 0) {
 210:                  buf.Append(NumToString((Int32) numeroLista[0],0));
 211:              }
 212:   
 213:              return buf.ToString();
 214:          }
 215:      }
 216:  }

 


Posted in: .Net , C#  Tags: ,

Páginas

Calendário

«  March 2010  »
MoTuWeThFrSaSu
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234
View posts in large calendar