Mostrando postagens com marcador C#. Mostrar todas as postagens
Mostrando postagens com marcador C#. Mostrar todas as postagens

sábado, 23 de maio de 2009

Generics - A great addition to .Net

Ver este post em Portugûes

Hello. In this post I'll show something very nice about .Net: Generics.

First, I'll show a simple struct in order to explain the feature:


struct Person {
public string Name;
public string Address;
public string Zip;
}


We have here a classic example of a data struct. Here we define fields with their respective data types (we're talking here about a strongly typed language). That means we have to provide the data type of the attributes at compile time. But, what if we could let the (struct's) user define what type s/he wants to use in their struct? How so? e.g.: A struct, two fields and their data type is open to the user to specify and set the attribute, making it "appear" a weakly typed language, but with the advantage of type checking at compile time.

Let's take a look at an example:


struct Pair<TClass1, TClass2>
where TClass1 : class
where TClass2 : class {

public TClass1 obj1;
public TClass2 obj2;
}


Here comes the generics: We define a struct, asking the user to provide which clases will will represent the TClass1 and TClass2, which we are defining that have to inherit the class object and it automatically defines what data type that fields inside will accept

The nice part is when we start to use this structure. Let's see another code block:


class Customer {
public int ID;
public string Name;

public override string ToString() {
return string.Format("Customer ID = {0}, Name = {1}", ID, Name);
}
}

class Product {
public int ID;
public string Name;

public override string ToString() {
return string.Format("Product ID = {0}, Name = {1}", ID, Name);
}
}

struct Pair<TClass1, TClass2>
where TClass1 : class
where TClass2 : class {

public TClass1 obj1;
public TClass2 obj2;
}

class Program {
static void Main(string[] args) {

var c = new Customer { ID = 1, Name = "Felipe" };
var p = new Product { ID = 1, Name = "Caneta BIC" };

var pair = new Pair<Customer, Product>() { obj1 = c, obj2 = p };

Console.WriteLine(pair.obj1.ToString());
Console.WriteLine(pair.obj2.ToString());

}
}


The braces after the new instanct are a new notation of C# that allows us to create new instances of classes and set values to public fields in the same instruction.

In the progem we create instances of Customer and Product and define these types as the relevant types for the struct Pair. Note that, after we define the struct with these types we can only inform instances of these types for the specific fields. The compiler doens't let us inform any other value; and even the IntelliSense indicates correctly.

I hope you all liked this post and again, sorry for my english, as I am no native English speaker. Thank you very much and see you next time.

Artigo completo (View Full Post)

Generics - Uma Grande adição a .Net

View this post in English

Olá a todos. Neste post vou mostrar algo muito legal a respeito da .Net: Generics.

Primeiro vou preparar o terreno para explicar o recurso: Vamos ter como exemplo uma estrutura básica:



struct Pessoa {
public string Nome;
public string Endereco;
public string CEP;
}


Nós temos aqui um exemplo clássico de uma estrutura de dados. Nela nós definimos campos com os tipos definidos de dados (claro, numa linguagem fortemente tipada). Isso significa que nós temos que fornecer os tipos de dados na hora em que a criamos. Mas, E se pudéssemos criar uma estrutura de dados onde o usuário (da estrutura, claro) escolha os tipos de dados dos atributos? Como assim? A estrutura possui dois atributos e o usuário diz de que tipo de dados são estes atributos antes de definir seus valores, tendo "aparência" de linguagem de tipagem fraca, mas com a vantagem de checagem de tipos em tempo de compilação.

Nada melhor para explicar do que um exemplo prático:


struct Par<TClasse1, TClasse2>
where TClasse1 : class
where TClasse2 : class {

public TClasse1 obj1;
public TClasse2 obj2;
}


Aqui vem o uso dos genéricos: Definimos uma estrutura, pedido que o usuário forneça dois tipo, TClasse1 e TClasse2, que dizemos abaixo que elas devem ser descendentes de object (ou object) e isso vira uma classe para ser referenciada dentro da struct.

A parte legal vem na hora em que começamos a utilizar esta estrutura. Abaixo tem mais um bloco de código:


class Cliente {
public int ID;
public string Nome;

public override string ToString() {
return string.Format("Cliente ID = {0}, Nome = {1}", ID, Nome);
}
}

class Produto {
public int ID;
public string Nome;

public override string ToString() {
return string.Format("Produto ID = {0}, Nome = {1}", ID, Nome);
}
}

struct Par<TClasse1, TClasse2>
where TClasse1 : class
where TClasse2 : class {

public TClasse1 obj1;
public TClasse2 obj2;
}

class Program {
static void Main(string[] args) {

var c = new Cliente { ID = 1, Nome = "Felipe" };
var p = new Produto { ID = 1, Nome = "Caneta BIC" };

var par = new Par<Cliente, Produto>() { obj1 = c, obj2 = p };

Console.WriteLine(par.obj1.ToString());
Console.WriteLine(par.obj2.ToString());

}
}



As chaves depois da nova instância das classes é uma facilidade do C# que nos permite criar uma nova instância de uma classe e atribuir valores aos membros públicos naquele momento.

Dentro do programa nós criamos instâncias das classes Cliente e Produto e definimos como atributos da nossa estrutura para usarmos depois. O detalhe é que, assim que nós definimos que as classes da estrutura são Cliente e Produto, o compilador não deixa nenhum outro valor; até o IntelliSense indica corretamente.

Espero que que vocês tenham gostado deste post e o assunto tenha despertado em vocês o interesse que despertou em mim. Muito obrigado e até a próxima.

Artigo completo (View Full Post)

sábado, 28 de março de 2009

Ajax-enabled Web Services with ScriptManager

Clique aqui para ver este post em Português

In this post I'll show an incredible ASP.Net feature I've learned recently: Ajax-enabled Web Services.

With the ScriptManager component (that we've already seen in this post) we're able to consume a Web Service in our Web Site and use the results in JavaScript with little to none specific programming effort. With this component, the Web Service looks like it's a client script object.


Let's start with a new Web Site in Visual Studio (the Visual Web Developer express edition works fine, too). Choose a folder to save the Web Site (you don't need the IIS installed in order to test de project). Now we'll create the Web Service.

Right-click the Web Site's root directory and choose Add New Item. In the dialog box select Web Service. Name it AjaxWs.asmx and click Ok. The IDE should open the file App_Code/AjaxWs.cs. This is where we're gonna work.

Let's leave its implementation as it is for now. It should come with a sample method HelloWorld. The only thing we'll do is "enable" the client script calls. To do that find the class definition:

public class AjaxWs : System.Web.Services.WebService


In the line above there's a commented class decoration that we only need to remove the comment bars to enable this feature:

// [System.Web.Script.Services.ScriptService]


So, remove the comment and save the file and click the menu Build > Build Web Site.

The Web Service part is done (for now). Now we're gonna code the Web Form that calls the Web Service. Open the Default.aspx file and go to the visualization "Source" or "Split". Below the form tag

<form id="form1" runat="server">


We're gonna add a ScriptManager component. You can drag it from the toolbox or simply type manually the asp:ScriptManager tag. The VS makes the effort of type the tags manually very smooth, even if it may not seem that way. After done the tag looks like this:

<asp:ScriptManager runat="server" ID="ScriptMngr">
<Services>
<asp:ServiceReference Path="~/AjaxWs.asmx" />
</Services>
</asp:ScriptManager>


We'll now create a client script block in our Web Form. Find the head section and add a script block inside. Here's the code:

<head runat="server">
<title>Untitled Page</title>
<script type="text/javascript">
function executarWs() {
AjaxWs.HelloWorld(
function(resultado) {
alert(resultado)
}
)
}
</script>
</head>


I'll give a brief explanation about this script:

AjaxWs - Our Web Service - was created by VS when we added the ScriptManager component and referenced the ~/AjaxWs.asmx Web Service. We're coding a method call to Hello World and pass a function as an argument - more precisely a callback. A callback is a function definition that is called when the function that took is as an argument needs. Think of it as some sort of event handler. But it's subject for another post.

Now we need to call this method. We've seen "new feature" part. Now we're gonna call our Web Service's methods as an ordinary JavaScript call. We'll create a HTML button to call the JavaScript function:

<button onclick="executarWs()">Clique aqui</button>


Here goes the complete WebForm's code:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
<script type="text/javascript">
function executarWs() {
AjaxWs.HelloWorld(
function(resultado) {
alert(resultado)
}
)
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="ScriptMngr">
<Services>
<asp:ServiceReference Path="~/AjaxWs.asmx" />
</Services>
</asp:ScriptManager>
<div>
<button onclick="executarWs()">Clique aqui</button>
</div>
</form>
</body>
</html>


Now run the Web Site (F5) to see what we've done in action. When we click the button the message "Hello World" will pop up. This alone is very nice already; but, what if we could return objects with properties instead of pure strings and ints? Well, we can!

First, let's create a class in our Web Site. Right click in the App_Code folder below the root folder and choose Add New Item. In the dialog box choose Class. Name it Pessoa.cs and click Ok. Here's the complete code:

public class Pessoa {

public string Nome { get; set; }
public string Sobrenome { get; set; }

}


Now let's get back to our Web Service and create a new method that take two parameters and returns an instance of Pessoa. Open the AjaxWs.cs again and add the following code under the HelloWorld method:

[WebMethod]
public Pessoa ObterPessoa(string nome, string sobrenome) {
return new Pessoa { Nome = nome, Sobrenome = sobrenome };
}


Now get back to Default.aspx and modify the HelloWorld method call to ObetrPessoa, giving the nome and sobrenome arguments before the callback argument:

function executarWs() {
AjaxWs.ObterPessoa(
"Estação",
"ZN",
function(resultado) {
alert(resultado.Nome + " " + resultado.Sobrenome)
}
)
}


Now run the Web Site again and see the result. Awesome! We had nearly zero effort and the possibilities are many with this technology. Thank you and take care.

Artigo completo (View Full Post)

Web Services em Ajax com ScriptManager

Click here to see this post in English

Neste post eu mostro uma facilidade incrível do ASP.Net que eu aprendi: Acessar Web Services via Ajax.

Com o componente ScriptManager - é o mesmo daquele post sobre ASP.Net e Ajax - podemos incluir referência para um Web Service criado no nosso WebSite, executá-lo e recuperar o resultado com um esforço mínimo de código. Com este componente parece que o Web Service é um objeto do próprio Script cliente da nossa página.


Bem, vamos começar criando projeto WebSite no Visual Studio (pode ser o Visual Web Developer Express Edition também). Escolham uma pasta para abrigar o WebSite (lembrando que para testar o VS inicia um servidor Web virtual com o nosso site) e pronto. Agora vamos criar nosso Web Service.

Clique com o botão direito na raiz do WebSite e selecione Add New Item. Na janela de New Item escolha Web Service. Chame de AjaxWs.asmx e clique Ok. A IDE vai abrir o arquivo App_Code/AjaxWs.cs. É nele que vamos trabalhar

Vamos Deixar a implementação dele como está por enquanto. Ele já vem com um método de exemplo HelloWorld. A única coisa que vamos fazer é "habilitar" que ele seja chamado por Script cliente. Para isso procure a definição da classe:

public class AjaxWs : System.Web.Services.WebService


Na linha acima desta há uma decoração comentada que nós só precisamos descomentar para adicionar esta funcionalidade:

// [System.Web.Script.Services.ScriptService]


Portanto descomente esta linha e salve o arquivo e chame o menu Build > Build Web Site.

A parte do Web Service está pronte (por enquanto). Agora vamos trabalhar no nosso WebForm para chamar este Web Service. Abra o arquivo Default.aspx e vá para a visualização "Source" ou "Split". Abaixo da tag do form

<form id="form1" runat="server">


vamos colocar um componente ScriptManager. Você pode arrastar da toolbox ou simplesmente digitar a tag. O VS deixa o tabalhar de digitar os componentes muito rápido e produtivo, apesar de parecer o contrário. Enfim, a tag fica assim depois de pronta:

<asp:ScriptManager runat="server" ID="ScriptMngr">
<Services>
<asp:ServiceReference Path="~/AjaxWs.asmx" />
</Services>
</asp:ScriptManager>


Com ele aí vamos criar um bloco de script na nossa página. Procure a seção <header> do WebForm e crie um bloco de script dentro. Abaixo está o código:

<head runat="server">
<title>Untitled Page</title>
<script type="text/javascript">
function executarWs() {
AjaxWs.HelloWorld(
function(resultado) {
alert(resultado)
}
)
}
</script>
</head>


Vou dar uma breve explicação sobre este script:

AjaxWs - que é o nome do nosso Web Service - foi definido automaticamente pelo VS quando nós colocamos o ScriptManager no WebForm. Estamos chamando o método HelloWorld do nosso Web Service e passando como argumento uma função - mais precisamente um callback. Um callback é uma definição de função que será chamado pela função que nós invocamos quando necessário. É um conceito semelhante ao de manipuladores de eventos. Em outro post eu me dedico somente a JavaScript.

Agora precisamos executar esta função de alguma maneira. A novidade da tecnologia já passou; agora podemos fazer como uma chamada normal de alguma função JavaScript. Para este exemplo vou criar um botão HTML no WebForm:

<button onclick="executarWs()">Clique aqui</button>


Abaixo segue o WebForm completo:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
<script type="text/javascript">
function executarWs() {
AjaxWs.HelloWorld(
function(resultado) {
alert(resultado)
}
)
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="ScriptMngr">
<Services>
<asp:ServiceReference Path="~/AjaxWs.asmx" />
</Services>
</asp:ScriptManager>
<div>
<button onclick="executarWs()">Clique aqui</button>
</div>
</form>
</body>
</html>


Agora execute o programa (F5) para ver o que nós fizemos em ação. Quando clicamos no botão a mensagem "Hello World" aparece. Isso por si só já é muito legal, mas imagine se, em vez de retornar somente uma string, pudéssemos retornar objetos com propriedades? Mas só pode!

Primeiro vamos criar uma classe no Web Site. Clique com o botão direito na pasta App_Code dentro da raiz do Web Site e clique Add New Item. Na janela selecione Class. chame o arquivo de Pessoa.cs e clique Ok. abaixo segue a classe pronta:

public class Pessoa {

public string Nome { get; set; }
public string Sobrenome { get; set; }

}


Agora vamos voltar no nosso Web Service e criar um novo método que pegue dois parâmetros e retorne uma instância de PEssoa. Abra o AjaxWs.cs outra vez e adicione o seguinte método abaixo do HelloWorld:

[WebMethod]
public Pessoa ObterPessoa(string nome, string sobrenome) {
return new Pessoa { Nome = nome, Sobrenome = sobrenome };
}


Agora volte no Default.aspx e modifique a chamada do método HelloWorld para ObterPessoa, passando agora os argumentos nome e sobrenome antes da função de callback:

function executarWs() {
AjaxWs.ObterPessoa(
"Estação",
"ZN",
function(resultado) {
alert(resultado.Nome + " " + resultado.Sobrenome)
}
)
}


Agora execute novamente e veja o resultado. Demais! Nosso esforço foi praticamente zero o as possibilidades são muitas com esta tecnologia. Um grande abraço a todos e até a próxima!

Artigo completo (View Full Post)

Ajax in a Simple way with ASP.NET

Clique aqui para ver este post em Português

Hello. In this post I'll show a very nice way to enable Ajax in our ASP.NET WebForms I learned.

When I (and most people) learned Ajax, the solution was to use a javascript object (XmlHttpRequest), create a separate script to process the request and write code to display the results that come in XML or plain text. I must confess that I always liked to work with Ajax, even with all that code effort xD

Another interesting point is the debugging and the error tracking.


In VS 2008 there are a couple of simple, but very useful components that allows us to work with Ajax in an easy and transparent way: ScriptManager and UpdatePanel.

To demonstrate the use of these components I'll create an ASP.NET WebForm that searches an object collection, and next add these componentes to enable Ajax. So, Let's start with an ASP.NET WebSite and edit the Default.aspx. Here goes the Markup source code:

<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Ajax com ASP.NET</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<p>
Busca: <asp:TextBox runat="server" ID="BuscaTxt" Width="200" /> 
<asp:Button runat="server" ID="BuscaBtn" Text="Buscar"
onclick="BuscaBtn_Click" />
</p>

<div>
<asp:GridView runat="server"
ID="PessoasGridView"
AutoGenerateColumns="false"
CellPadding="4"
CellSpacing="0">
<Columns>
<asp:BoundField DataField="Nome"
HeaderText="Nome"
HeaderStyle-Width="200" />
<asp:BoundField DataField="Sobrenome"
HeaderText="Sobrenome"
HeaderStyle-Width="200" />
</Columns>
</asp:GridView>
</div>
</div>
</form>
</body>
</html>


Now the source code of Default.aspx.cs:

using System;
using System.Collections.Generic;
using System.Linq;

public partial class _Default : System.Web.UI.Page {

class Pessoa {
public string Nome { get; set; }
public string Sobrenome { get; set; }
}

private List<Pessoa> Pessoas = new List<Pessoa>{
new Pessoa { Nome = "Felipe", Sobrenome = "Guerço" },
new Pessoa { Nome = "Gerson", Sobrenome = "Motta" },
new Pessoa { Nome = "Joaquim", Sobrenome = "José" },
new Pessoa { Nome = "João", Sobrenome = "Silva" },
new Pessoa { Nome = "Aristarco", Sobrenome = "Pederneiras" },
};

protected void Consultar() {
PessoasGridView.DataSource =
from p in Pessoas
where p.Nome.Contains(BuscaTxt.Text)
orderby p.Nome
select p;
PessoasGridView.DataBind();
}

protected void Page_Load(object sender, EventArgs e) {

}
protected void BuscaBtn_Click(object sender, EventArgs e) {
Consultar();
}
}


With that we can query the private member Pessoas according to the filter criteria in the textbox. But this way each request will produce a full round trip just to update the grid contents. Let's see how to avoid this with the Ajax components.

We'll add the ScriptManager component in our WebForm in order to enable Ajax. Next we'll add the UpdatePanel and put the grid "inside" it.

The UpdatePanel is a very interesting component. It represents a "piece" of the WebForm that is updated when certain events are fired up. But which events? Here comes the interesting part: We configure which component's events we want to "trigger" the update panel. In other words: When that action fires up the only part updated is the content inside the UpdatePanel. Let's see the markup here:

<asp:UpdatePanel runat="server" ID="GridUpdatePanel">
<Triggers>
<asp:AsyncPostBackTrigger
ControlID="BuscaBtn" EventName="Click" />
</Triggers>
<ContentTemplate>
<asp:GridView runat="server"
ID="PessoasGridView"
AutoGenerateColumns="false"
CellPadding="4"
CellSpacing="0">
<Columns>
<asp:BoundField DataField="Nome"
HeaderText="Nome"
HeaderStyle-Width="200" />
<asp:BoundField DataField="Sobrenome"
HeaderText="Sobrenome"
HeaderStyle-Width="200" />
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>


Now the entire WebForm markup:

<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Ajax com ASP.NET</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="AjaxScriptManager" />
<div>
<p>
Busca: <asp:TextBox runat="server" ID="BuscaTxt" Width="200" /> 
<asp:Button runat="server" ID="BuscaBtn" Text="Buscar"
onclick="BuscaBtn_Click" />
</p>

<div>
<asp:UpdatePanel runat="server" ID="GridUpdatePanel">
<Triggers>
<asp:AsyncPostBackTrigger
ControlID="BuscaBtn" EventName="Click" />
</Triggers>
<ContentTemplate>
<asp:GridView runat="server"
ID="PessoasGridView"
AutoGenerateColumns="false"
CellPadding="4"
CellSpacing="0">
<Columns>
<asp:BoundField DataField="Nome"
HeaderText="Nome"
HeaderStyle-Width="200" />
<asp:BoundField DataField="Sobrenome"
HeaderText="Sobrenome"
HeaderStyle-Width="200" />
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</div>
</form>
</body>
</html>


Try to run the WebSite and notice that the page doesn't refresh anymore. And the best part is that we didn't need to write any javascript code and create any "support" files.

Thank you for the support and until next time.

Artigo completo (View Full Post)

Ajax de um jeito simples em ASP.NET

Click here to see this post in English

Olá a todos. Neste post vou mostrar uma maneira de implementar Ajax no ASP.NET muito legal que eu aprendi.

Quando eu (e a grande maioria) aprendi Ajax a maneira de se fazer era usar um objeto javascript (XmlHttpRequest), criar uma página separada para processar o request e montar o resultado em XML ou texto plano, e tratar este resultado no nosso script principal. Eu confesso que eu sempre achei muito legal programar com Ajax, apesar do trabalhão que dá xD.


Outra parte interessante é o trabalho que dá para depurar e corrigir errors.

No VS 2008 eu vi uns componentes simples, mas que nos permitem trabalhar com Ajax de maneira muito simples e transparente: ScriptManager e UpdatePanel.

Para mostrar o uso destes componentes vou criar uma pequena página ASP.NET que vai fazer uma consulta numa coleção de strings e depois adicionar funcionalidade Ajax a esta página. Para isso vou partir de um WebSite ASP.NET e editar a Default.aspx. Abaixo segue o código-fonte HTML:

<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Ajax com ASP.NET</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<p>
Busca: <asp:TextBox runat="server" ID="BuscaTxt" Width="200" /> 
<asp:Button runat="server" ID="BuscaBtn" Text="Buscar"
onclick="BuscaBtn_Click" />
</p>

<div>
<asp:GridView runat="server"
ID="PessoasGridView"
AutoGenerateColumns="false"
CellPadding="4"
CellSpacing="0">
<Columns>
<asp:BoundField DataField="Nome"
HeaderText="Nome"
HeaderStyle-Width="200" />
<asp:BoundField DataField="Sobrenome"
HeaderText="Sobrenome"
HeaderStyle-Width="200" />
</Columns>
</asp:GridView>
</div>
</div>
</form>
</body>
</html>


Agora o código Default.aspx.cs:

using System;
using System.Collections.Generic;
using System.Linq;

public partial class _Default : System.Web.UI.Page {

class Pessoa {
public string Nome { get; set; }
public string Sobrenome { get; set; }
}

private List<Pessoa> Pessoas = new List<Pessoa>{
new Pessoa { Nome = "Felipe", Sobrenome = "Guerço" },
new Pessoa { Nome = "Gerson", Sobrenome = "Motta" },
new Pessoa { Nome = "Joaquim", Sobrenome = "José" },
new Pessoa { Nome = "João", Sobrenome = "Silva" },
new Pessoa { Nome = "Aristarco", Sobrenome = "Pederneiras" },
};

protected void Consultar() {
PessoasGridView.DataSource =
from p in Pessoas
where p.Nome.Contains(BuscaTxt.Text)
orderby p.Nome
select p;
PessoasGridView.DataBind();
}

protected void Page_Load(object sender, EventArgs e) {

}
protected void BuscaBtn_Click(object sender, EventArgs e) {
Consultar();
}
}


Com isso nosso programa vai consultar a lista no membro privado Pessoas de acordo com o filtro. Mas dessa forma a página está fazendo uma viagem completa ao servidor só para atualizar o grid. Vamos ver como evitar isso com os componentes de Ajax do ASP.NET.

Na página vamos colocar o componente ScriptManager para habilitar o uso do componente que vai realizar o Ajax. Em seguida vamos colocar na página o componente UpdatePanel e colocar o grid dentro dele.

O componente UpdatePanel é muito interessante: Ele representa um "pedaço" do WebForm que vai ser atualizado quando determinada ação acontecer. Mas que ação? Agora vem a parte interessante: No UpdatePanel nós configuramos quais eventos de quais objetos vão disparar o refresh daquela área. Vou colocar só o trecho do grid aqui:

<asp:UpdatePanel runat="server" ID="GridUpdatePanel">
<Triggers>
<asp:AsyncPostBackTrigger
ControlID="BuscaBtn" EventName="Click" />
</Triggers>
<ContentTemplate>
<asp:GridView runat="server"
ID="PessoasGridView"
AutoGenerateColumns="false"
CellPadding="4"
CellSpacing="0">
<Columns>
<asp:BoundField DataField="Nome"
HeaderText="Nome"
HeaderStyle-Width="200" />
<asp:BoundField DataField="Sobrenome"
HeaderText="Sobrenome"
HeaderStyle-Width="200" />
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>


Segue abaixo a página modificada:

<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Ajax com ASP.NET</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="AjaxScriptManager" />
<div>
<p>
Busca: <asp:TextBox runat="server" ID="BuscaTxt" Width="200" /> 
<asp:Button runat="server" ID="BuscaBtn" Text="Buscar"
onclick="BuscaBtn_Click" />
</p>

<div>
<asp:UpdatePanel runat="server" ID="GridUpdatePanel">
<Triggers>
<asp:AsyncPostBackTrigger
ControlID="BuscaBtn" EventName="Click" />
</Triggers>
<ContentTemplate>
<asp:GridView runat="server"
ID="PessoasGridView"
AutoGenerateColumns="false"
CellPadding="4"
CellSpacing="0">
<Columns>
<asp:BoundField DataField="Nome"
HeaderText="Nome"
HeaderStyle-Width="200" />
<asp:BoundField DataField="Sobrenome"
HeaderText="Sobrenome"
HeaderStyle-Width="200" />
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</div>
</form>
</body>
</html>


E o mais legal é que nós criamos zero de código javascript para habilitar Ajax no nosso WebForm.

Um grande abraço a todos e até a próxima.

Artigo completo (View Full Post)

segunda-feira, 23 de junho de 2008

Linq to SQL - Working with Databases

Clique aqui para ver a versão em português deste post

In this post I continue to show the Linq technology. This tiime we'll see how it's used to access and manipulate data in relational database tables.

In order to use Linq with databases we need to establish a relationship between the business objects in our software and the database tables. To achieve this we use the class/attributes mapping.

This mapping is simple: We create a class that represent a database table and in this class we set which table it is mapped to. In the attributes we set to which database fields they're mapped.

In the current version, Linq only supports the MS SQL Server, but there are already many developers out there working on solutions to cover other RDBMSs too.

To begin let's show a table in the database: Produtos

CREATE TABLE [dbo].[Produtos](
[ProdutoID] [uniqueidentifier] ROWGUIDCOL
NOT NULL CONSTRAINT [DF_Produtos_ProdutoID] DEFAULT (newid()),
[Descricao] [nvarchar](100) COLLATE Latin1_General_CI_AS NOT NULL,
[Preco] [decimal](10, 2) NOT NULL,
[Saldo] [int] NOT NULL,
[Versao] [timestamp] NOT NULL
)


Let's pay close attention at the column Versao, type timestamp. This datatype stores the record version. This is very useful to work with optimistic updates and concurrency issues and Linq makes good use of it.

Before we advance, insert some records in this table.

Now let's create a class that uses this table. In order to use Linq to SQL we need to add reference to the assembly System.Data.Linq to the project. Here is the code:

using System;
using System.Data.Linq.Mapping;

[Table(Name="Produtos")]
class Produto {

[Column(IsPrimaryKey = true,
IsDbGenerated = true,
AutoSync = AutoSync.OnInsert)]
public Guid ProdutoID { get; set; }

[Column(CanBeNull = false)]
public string Descricao { get; set; }

[Column(CanBeNull = false)]
public decimal Preco { get; set; }

[Column(CanBeNull = false)]
public int Saldo { get; set; }

[Column(IsDbGenerated = true,
IsVersion = true, AutoSync = AutoSync.Always)]
public System.Data.Linq.Binary Versao { get; set; }
}


Now let's create a Linq query in this database table. Up until here we just defined the entity and attributes mapping, but we didn't define anything about the database itself. How do we do that?

There is an object in Linq called DataContext. We can think of it more like a database connection in other technologies, but it hardly acts like. It does so much more! It's responsible for the database connection, making and the exectution of the queries, mapping, record updates and even transactions and record concurrency!

We just need to create a instance and it does everything on its own. In other words, we don't need to make code to open or close connection, build string queries and treat results anymore. Let's see the code:

using System;
using System.Data.Linq;
using System.Linq;

class Program {
static void Main(string[] args) {

var connStr = @"Data Source=.\SQLEXPRESS;Initial Catalog=DadosSql;User ID=felipe;Password=123";

using (var db = new DataContext(connStr)) {
var Produtos = db.GetTable<Produto>();

var qry =
from p in Produtos
orderby p.Descricao
select p;

foreach (var prod in qry) {
Console.WriteLine("{0}, {1}, {2}", prod.Descricao,
prod.Preco,
prod.Saldo);
}
}
}
}


What we've done:

- Created a DataContext to connect to the database;
- Created a local variable to represent our mapped table;
- Built the query;
- Display the results;

The wonder of wonders is: Will the DataContext retrieve the entire Produtos table when we create the local variable Produtos? Answer is no! Then, will it occur when we create the qry? Nope. So, where is it?

One of the coolest things in Linq is the ability to send the query to the database only at the moment its data is actually required. In our case, in the foreach loop. That query returned an instance of IOrderedQueryable that seems like a List. But it isn't quite a common list. When its data is required the DataContext build a query based on its definition and send the query to the database and then convert the resultset in an object list, thanks to the mapping features. This technique is called Deferred execution.

How would we do in order to open connection, build a parametrized query and convert the resultset in a list of instances of our business object? And all other tables?

I'll change the code a bit and add some verbose. The DataContext has a property called Log that allows us to view the DataContext's log:

using System;
using System.Data.Linq;
using System.Linq;

class Program {
static void Main(string[] args) {

var connStr = @"Data Source=.\SQLEXPRESS;Initial Catalog=DadosSql;User ID=felipe;Password=123";

using (var db = new DataContext(connStr)) {
db.Log = Console.Out;

Console.WriteLine("** Pegando a tabela Produtos");
var Produtos = db.GetTable<Produto>();

Console.WriteLine("** Criando a query");
var qry =
from p in Produtos
where p.Descricao.Contains("a")
orderby p.Descricao
select p;

Console.WriteLine("** Começando a iteração");
foreach (var prod in qry) {
Console.WriteLine("{0}, {1}, {2}", prod.Descricao,
prod.Preco,
prod.Saldo);
}
}
}
}


Here's the console output:

** Pegando a tabela Produtos
** Criando a query
** Começando a iteração
SELECT [t0].[ProdutoID], [t0].[Descricao], [t0].[Preco], [t0].[Saldo], [t0].[Ver
sao]
FROM [Produtos] AS [t0]
WHERE [t0].[Descricao] LIKE @p0
ORDER BY [t0].[Descricao]
-- @p0: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [%a%]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.8

Caderno Universitário 500 folhas, 7,90, 50
Caneta BIC, 1,99, 25
Lapiseira 0,7mm, 5,00, 10
Pasta polionda A4, 2,40, 6


The DataContext produces a query with parameters, instead of concatenate the criteria and build one simple query string. This is very nice, because the RDBMS can make an execution plan for this query and use the same play every time we run this query, even with different parameter values. It means better performance.

Well, that's it for this post, but Linq to SQL goes way further than this. In the next issue I'll write about CRUD operations with Linq to SQL. Thnnk you and take care.

Artigo completo (View Full Post)

Linq to SQL - Trabalhando com bancos de dados

Click here to see this post in English

Neste post vou continuar a mostrar sobre a tecnologia Linq. Desta vez veremos como ela é usada para acessar e manipular dados em tabelas de bancos de dados relacionais.

Para habilitar Linq para acessar bancos de dados nós precisamos primeiro estabelecer relações entre os objetos de negócio do nosso software e as tabelas do banco de dados. Para isso usamos mapeamento de classe/abtributos.

Este mapeamento é simples: Nós criamos uma classe que representa uma tabela do banco de dados e nesta classe nós indicamos qual tabela do banco de dados ela representa. Nas propriedades desta classe nós marcamos quais propriedades representam quais campos da tabela.

Na versão atual Linq suporta apenas o MS SQL Server, mas há desenvolvedores por aí que já estão trabalhando no suporte a outros bancos também.

Para começar vamos mostrar uma tabela no banco de dados: Produtos

CREATE TABLE [dbo].[Produtos](
[ProdutoID] [uniqueidentifier] ROWGUIDCOL
NOT NULL CONSTRAINT [DF_Produtos_ProdutoID] DEFAULT (newid()),
[Descricao] [nvarchar](100) COLLATE Latin1_General_CI_AS NOT NULL,
[Preco] [decimal](10, 2) NOT NULL,
[Saldo] [int] NOT NULL,
[Versao] [timestamp] NOT NULL
)


Atenção especial à coluna Versao, do tipo timestamp. Esta coluna armazena a versão do registro. Ela é útil para efeitos de atualizações otimistas e concorrência e Linq faz ótimo uso dela.

Antes de continuar insira alguns registros nesta tabela.

Agora vamos codificar uma classe que faça uso desta tabela. Para utilizar Linq devemos adicionar referência no projeto para o assembly System.Data.Linq. Abaixo segue o código da classe:

using System;
using System.Data.Linq.Mapping;

[Table(Name="Produtos")]
class Produto {

[Column(IsPrimaryKey = true,
IsDbGenerated = true,
AutoSync = AutoSync.OnInsert)]
public Guid ProdutoID { get; set; }

[Column(CanBeNull = false)]
public string Descricao { get; set; }

[Column(CanBeNull = false)]
public decimal Preco { get; set; }

[Column(CanBeNull = false)]
public int Saldo { get; set; }

[Column(IsDbGenerated = true,
IsVersion = true, AutoSync = AutoSync.Always)]
public System.Data.Linq.Binary Versao { get; set; }
}


Agora vamos criar uma query Linq nesta tabela do banco. Até aqui nós definimos o mapeamento da entidade e dos campos, mas nós não definimos nada sobre o banco de dados. Como faremos isso?

Há uma classe em Linq chamada DataContext. Podemos pensar nela como se fosse um objeto de conexão com um banco de dados, mas o DataContext vai além disso. Ele é responsável pela conexão com o banco de dados, montagem e execução das queries, tratamento dos resultados, cuida das operações de atualização dos registros e até cuida de transações e concorrência de registros!

Para isso só devemos instanciá-lo e ele faz tudo automaticamente! Ou seja, nós não precisamos mais criar códigos para abrir conexão, fechar conexão, montar queries em string, tratar resultados... Vamos ver na prática:

using System;
using System.Data.Linq;
using System.Linq;

class Program {
static void Main(string[] args) {

var connStr = @"Data Source=.\SQLEXPRESS;Initial Catalog=DadosSql;User ID=felipe;Password=123";

using (var db = new DataContext(connStr)) {
var Produtos = db.GetTable<Produto>();

var qry =
from p in Produtos
orderby p.Descricao
select p;

foreach (var prod in qry) {
Console.WriteLine("{0}, {1}, {2}", prod.Descricao,
prod.Preco,
prod.Saldo);
}
}
}
}


Vamos repassar:

- Criamos um DataContext para conectar ao nosso banco de dados;
- Criamos uma variável local para ser a definição da nossa tabela mapeada;
- Fazemos a query extraindo dados desta "tabela";
- Exibimos os resultados.

A parte mais legal é: Será que o DataContext vai trazer a tabela Produtos inteira quando passar pela linha de código onde criamos a variável Produtos? A resposta é não! Então, quando o banco vai na tabela Produtos? Na linha onde criamos a qry? Também não! Ora, então onde é?

Uma das características mais legais do Linq to SQL é a habilidade de executar a query no banco apenas no momento em que seus dados são utilizados. No nosso caso, no loop foreach. Aquela query produziu a variável qry do tipo IOrderedQueryable que, parece, é uma lista. Tem até foreach! Mas ela não guarda as informações nela no momento em que é instanciada. Quando o software "requer" os dados desta "lista", ela produz uma instrução SQL select e traz do banco os resultados, transformando-os em uma coleção de instâncias da classe Produto, através do mapeamento. Isso é chamado Deferred execution.

Como iríamos fazer para abrir conexão com o banco de dados, criar uma query parametrizada e transformar um resultset de datarows em uma lista de instâncias de Produto? E para todas as outras tabelas?

Para reforçar o que foi dito acima, vamos ver o log do DataContext para ver o que ele faz e como faz. Vou adicionar algumas linhas de código ao nosso exemplo anterior e ele vai ficar assim:

using System;
using System.Data.Linq;
using System.Linq;

class Program {
static void Main(string[] args) {

var connStr = @"Data Source=.\SQLEXPRESS;Initial Catalog=DadosSql;User ID=felipe;Password=123";

using (var db = new DataContext(connStr)) {
db.Log = Console.Out;

Console.WriteLine("** Pegando a tabela Produtos");
var Produtos = db.GetTable<Produto>();

Console.WriteLine("** Criando a query");
var qry =
from p in Produtos
where p.Descricao.Contains("a")
orderby p.Descricao
select p;

Console.WriteLine("** Começando a iteração");
foreach (var prod in qry) {
Console.WriteLine("{0}, {1}, {2}", prod.Descricao,
prod.Preco,
prod.Saldo);
}
}
}
}


Olha aqui a saída do console:

** Pegando a tabela Produtos
** Criando a query
** Começando a iteração
SELECT [t0].[ProdutoID], [t0].[Descricao], [t0].[Preco], [t0].[Saldo], [t0].[Ver
sao]
FROM [Produtos] AS [t0]
WHERE [t0].[Descricao] LIKE @p0
ORDER BY [t0].[Descricao]
-- @p0: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [%a%]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.8

Caderno Universitário 500 folhas, 7,90, 50
Caneta BIC, 1,99, 25
Lapiseira 0,7mm, 5,00, 10
Pasta polionda A4, 2,40, 6


A query que o DataContext produziu foi parametrizada, em vez de ter os valores concatenados. Isso é muito bom, porque o SGBD faz o plano de execução e deixa ele em cache, para que outras consultas que apenas tenham parâmetros diferentes usem o plano de execução que já foi calculado, trazendo melhor performance.

Com isso chegamos ao fim da nossa primeira visão sobre Linq to SQL e em outros posts vamos ver sobre as oeprações de CRUD com Linq to SQL. Até lá e muito obrigado.

Artigo completo (View Full Post)

terça-feira, 27 de maio de 2008

Linq to Objects - Parte 2

Click here to read this post in English

Olá a todos. Vou dar continuidade ao post anterior sobre Linq to Objects e mostrar algumas outras funcionalidades desta tecnologia que eu tenho achado tão legal. Espero que vocês também achem legal à medidade que eu vou mostrando as coisas que eu tenho visto e estudado. Vamos nessa!

Nos posts anteriores eu mostrei a sintaxe de query do Linq, mas há uma outra forma de fazer consultas com Linq. Todas as instruções (até mais algumas) que usamos nas queries Linq podem ser representada por chamadas de métodos das classes de coleções. Vamos fazer uma consulta na nossa lista do outro post:

var Meses = new List<string> {
"Janeiro",
"Fevereiro",
"Março",
"Abril",
"Maio",
"Junho",
"Julho",
"Agosto",
"Setembro",
"Outubro",
"Novembro",
"Dezembro"
};

var MesesComJ =
Meses
.Where(mes => mes.StartsWith("J"))
.OrderByDescending(mes => mes)
.Select(mes => mes);

foreach (var m in MesesComJ) {
Console.WriteLine(m);
}


Esta forma, na minha opinião, não é tão legal quanto a outra, mas com certeza também é legal e também mostra de forma clara o que o código quer recuperar.

Para listas simples o select é opcional, mas apenas na forma de métodos - na sintaxe de query é obrigatório.

Hey, que operador maluco é aquele ali? Qual, o =>? Ele é o operador usado para Lambda Expressions. Ah, legal... Mas o que são Lambda Expressions?

Alguns métodos de objetos aceitam como argumento uma definição de função em vez de um valor fixo. Vamos rever o caso do .Where:

.Where(mes => mes.StartsWith("J"))


Vale lembrar que este é um único parâmetro que está sendo passsado para o método. Quando a função fizer a iteração completa na lista ela vai usar este parâmetro para decidir se o item que está na dada posição vai retornar na lista resultante ou não.

Para isso nós definimos a função ali, na hora, criando a condição de retorno de registro. Mas para criar o filtro nós precisamos do contexto. É aí que entra o operador "goes to" (vai para). Ele serve para indicar qual é o contexto da função que estamos criando. Esta condição vai ser testada para cada item da lista (mes.StartsWith("J")), onde mes é o elemento corrente da lista, ou seja: para cada linha da iteração mes será o item corrente. Este tipo de expressão é comum em linguagens funcionais. Vale lembrar que o nome da variável antes do operador é definida por nós, e o código do outro lado deve usar o mesmo nome.

Há muitas expressões de query em Linq; e mesmo que eu soubesse todas este post seria quilométrico! Vamos aqui ver mais dois interessantes: Skip e Take.

Em C# não há representação para Skip e Take na sintaxe de query, somente em métodos. O Skip serve para "pular" resultados e o Take para "pegar" um certo número de linhas:

var Meses456 =
Meses
.Skip(3)
.Take(3);


O resultado será:

Abril
Maio
Junho


A chamada e a ordem dos métodos já nos diz o que a consulta vai retornar: "Pule 3 itens e pegue 3".

Dá para combinar a linguagem de query e as expressões também:

var MesesCom5Letras = (
from mes in Meses
where mes.Length == 5
orderby mes descending
select mes)
.Skip(1)
.Take(2);


O resultado será:

Junho
Julho


À medida em que eu vou aprendendo coisas novas eu posto aqui para o pessoal do Estação. Até treinem e postem aqui suas experiências também. Um grande abraço e até a próxima.

Artigo completo (View Full Post)

Linq to Objects - Part 2

Clique aqui para ler este post em Português

Hello everyone. I'll continue to talk about Linq to Objects in this post and show some other features present in this technology I have found very nice. I really hope you all like it as I continue to show the things I have seen and learned. Let's get to it.

In the previous posts I've shown the Linq query syntax, but there's another way to query data with Linq. All of the statements (in fact even more than that) we see in the query syntax can be represented by Collections' special method calls. They're called query expressions. Let's take a look at the previous example, this time using the method calls:

var Meses = new List<string> {
"Janeiro",
"Fevereiro",
"Março",
"Abril",
"Maio",
"Junho",
"Julho",
"Agosto",
"Setembro",
"Outubro",
"Novembro",
"Dezembro"
};

var MesesComJ =
Meses
.Where(mes => mes.StartsWith("J"))
.OrderByDescending(mes => mes)
.Select(mes => mes);

foreach (var m in MesesComJ) {
Console.WriteLine(m);
}


This form, imho, is not as cool as the another one, but it's also nice and shows us clearly what the code is going to get too.

Working with simple lists the select call is optional, but only in query expressions - in query syntax is still mandatory.

Hey, what is that weird operator over there? What, the =>? This is the operator we use for Lambda Expressions. Oh, ok... But, what are Lambda Expressions?

Some object methods take a function definition as an argument instead of a fixed value. Let's see the Where line again:

.Where(mes => mes.StartsWith("J"))


Let's note that there's only one argument passed to the method. When the Where method do the full iteration over the list it'll use the funcion defined in this argument to decide if the item at the given position will return in the result list or not.

For that we define the function right there, on the fly, creating the return condition for the items. But to create a dynamic filter we need a context. And here comes the "goes to" operator. It's used to point out what is the context in the function we're defining. This condition is going to be tested for each item in the main list, where mes is the current item. Use of this kind of expression is common in functional languages. The variable name before the operator is defined by us, and the code on the right side have to use the same name.

There are many query expressions in Linq; and even if I knew all of them this post would take ages! Let's see here other two interesting ones: Skip and Take.

There's no representation for Skip and Take in the query syntax in C#, only via method calls. Well, the Skip "Skips" a given number of items and the Take "Takes" a given number of items of the result.

var Meses456 =
Meses
.Skip(3)
.Take(3);


This'll produce the result:

Abril
Maio
Junho


The order of the methods call already gives us a tip of what's goind to happen: "Skip 3 and take the 3 next".

We can combine the query syntax with query expressions too:

var MesesCom5Letras = (
from mes in Meses
where mes.Length == 5
orderby mes descending
select mes)
.Skip(1)
.Take(2);


Resulting:

Junho
Julho


As I'm lerning new stuff I post here for you guys. Until there practice a bit and post your experiences here too. Thank you for the support and take care.

Artigo completo (View Full Post)

segunda-feira, 26 de maio de 2008

Linq to Objects - Consultando dados em memória

Click here to see the English version of this post

Olá a todos. O assunto deste post continua sobre a tecnologia Linq, mas desta vez vamos ver um segmento específico: Linq to Objects.

Antes de começar vou recomendar a todos o livro sobre Linq que estou lendo agora: Linq in Action, dos autores Fabrice Marguerie, Steve Eichert, Jim Wooley, publicado por Manning. Eu não encontrei literatura em português para Linq, então dois grandes amigos meus (Claudão e Fernandão) me deram de presente de aniversário. Um dos melhores presentes que eu já recebi até hoje hehe. Valeu galera! Além de cobir Linq ainda mostra muito de C# e boas práticas.

Voltando à tecnologia. Esta tecnologia nos permite realizar consultas em coleções de dados em memória. instâncias do tipo array, List e outras que implementam a interface IEnumerable podem ser usados com Linq. Basta adicionar o namespace System.Linq no nosso arquivo de código que já podemos utilizar o Linq.

Linq to Objects é particularmente útil quando precisamos obter dados de uma coleção em memória e adicionar funcionalidades de filtro e/ou ordenação. Estas tarefas feitas sem o Linq requerem uma boa quantidade de código para ser implementadas usando loops e variáveis temporárias. Outra vantagem de usar o modo de queries do Linq to Objects é a maior legibilidade do código e facilidade de manutenção e depuração, visto que a instrução mostra claramente o que vamos obter como resultado. Vamos a um exemplo prático:

string[] Meses = {"Janeiro",
"Fevereiro",
"Março",
"Abril",
"Maio",
"Junho",
"Julho",
"Agosto",
"Setembro",
"Outubro",
"Novembro",
"Dezembro"};

var MesesComJ =
from mes in Meses
where mes.StartsWith("J")
orderby mes descending
select mes;

foreach (var m in MesesComJ) {
Console.WriteLine(m);
}


O resultado será:

Junho
Julho
Janeiro


Como seria para gerar este mesmo resultado sem Linq? Se quiser se divertir um pouco e praticar algoritmos, fique à vontade :)

Agora imagine se, em vez de um array de strings pudéssemos fazer uma query com uma lista de objetos? E é possível:

class Program {

class Pessoa {
public string Nome { get; set; }
public string Sobrenome { get; set; }
}

static void Main(string[] args) {

var Felipe = new Pessoa { Nome = "Felipe", Sobrenome = "Guerço" };
var Gerson = new Pessoa { Nome = "Gerson", Sobrenome = "Motta" };

var Pessoas = new List<Pessoa> {Gerson, Felipe};

var qry =
from pessoa in Pessoas
orderby pessoa.Nome
select pessoa;

foreach (var p in qry) {
Console.WriteLine("{0} {1}", p.Nome, p.Sobrenome);
}
}
}


Aqui só vou desviar um pouco do Linq para mostrar novos recursos da linguagem C# para quem não conhece. Primeiro, auto propriedades:

public string Nome { get; set; }


Esta implementação cria a propriedade e, por trás das cortinas, cria os campos encapsulados para armazenar os valores das propriedades públicas. Muito útil para aquelas propriedades que são lidas e escritas diretamente nos campos, sem lógica de validação, ao mesmo tempo que deixa preparado para o futuro, sendo necessário somente terminar a implementação porque a propriedade já está definida.

Depois, tipos inferidos pelo compilador:

var Felipe = new Pessoa { Nome = "Felipe", Sobrenome = "Guerço" };


Nas versões anteriores nós tínhamos que definir o tipo da variável antes de inicializá-la. Com esta nova técnica o compilador infere o tipo da variável de acordo com o valor que é passado na inicialização. Não se engane: a definição de tipo ainda é forte, apenas nós não precisamos repetir o que a inicialização já diz. O compilador mesmo assim infere o tipo de dados correto na variável. Para variáveis declaradas sem inicialização nós ainda devemos definir o tipo previamente.

Por fim, um construtor especial:

var Felipe = new Pessoa { Nome = "Felipe", Sobrenome = "Guerço" };


Este construtor nos permite criar uma nova instância de uma classe já definindo suas propriedades.

Agora voltando ao Linq. Aqui selecionamos todas as pessoas da lista ordenando pela propriedade Nome. Se quiséssemos, poderíamos adicionar um filtro por nome adicionando uma cláusula where na consulta:

where pessoa.Nome.Contains("xxx")


Legal né. Mas ainda tem mais! Podemos juntar na mesma query coleções de dados relacionados:


class Program {

class Pessoa {
public string Nome { get; set; }
public string Sobrenome { get; set; }
}

class Pet {
public string Nome { get; set; }
public Pessoa Dono { get; set; }
}

static void Main(string[] args) {

var Felipe = new Pessoa { Nome = "Felipe", Sobrenome = "Guerço" };
var Gerson = new Pessoa { Nome = "Gerson", Sobrenome = "Motta" };

var Meg = new Pet { Nome = "Meg", Dono = Felipe };
var Rex = new Pet { Nome = "Rex", Dono = Gerson };
var Max = new Pet { Nome = "Max", Dono = Gerson };
var Nina = new Pet { Nome = "Nina", Dono = Felipe };

var Pets = new List<Pet> { Meg, Rex, Max, Nina };

var qry =
from pet in Pets
orderby pet.Dono.Nome
select new {
NomeDono = pet.Dono.Nome + ' ' + pet.Dono.Sobrenome,
NomePet = pet.Nome
};

foreach (var p in qry) {
Console.WriteLine("{0} {1}", p.NomeDono, p.NomePet);
}

}
}


Agora veremos mais um recurso interessante: Anonymous types.

select new {
NomeDono = pet.Dono.Nome + ' ' + pet.Dono.Sobrenome,
NomePet = pet.Nome
};


Aqui definimos um novo tipo (anônimo porque é definido ao mesmo tempo em que inicializamos as propriedades). Agora temos um objeto com as propriedades NomeDono e NomePet. O compilador define automaticamente os tipos de dados das propriedades de acordo com sua inicialização.

Agora vamos fazer uma pequena totalização. Vamos mostrar o dono e quantos pets ele possui:

var qry2 =
from pet in Pets
group pet by pet.Dono.Nome + ' ' + pet.Dono.Sobrenome into donos
select new {
Nome = donos.Key,
Pets = donos.Count()
};

foreach (var p in qry2) {
Console.WriteLine("Pets de {0}: {1}", p.Nome, p.Pets);
}


Agora nós criamos um grupo na query agrupando pets com a chave sendo o nome do dono. Neste grupo temos a propriedade Key, que representa o que estamos agrupando. Aí projetamos no resultado a chave do grupo e o contador de registros de cada grupo.

Antes de acabar vou fazer somente uma ressalva: Podemos usar estes resultados como fontes de dados para qualquer controle data-aware de WinForms ou WebForms (GridView, por exemplo).

Bem pessoal, acabou ficando com um tamanho legal, mas espero que tenha mostrado a quem ainda não conhecia como o Linq to Objects pode ser uma boa opção para trabalhar com dados em memória em nossas soluções. Grande abraço e até a próxima!

Artigo completo (View Full Post)

Linq to Objects - Querying in-memory collections

Clique aqui para ver a versão em português deste post

Hello everyone. This post's issue continues about the Linq technology, but this we'll see a specific segment: Linq to Objects.

Before we begin, I want to recommend the book about Linq that I'm reading now: Linq in Action, from the authors Fabrice Marguerie, Steve Eichert, Jim Wooley, published by Manning. It's indeed a great book and will cover not only Linq, but C# features and best practices as well.

Let's get back to Linq to Objects. This technology allows us to query in-memory data collections. Instances of type array, List and others that implement the IEnumerable interface can be used with Linq to Objects. You only need to add a using entry to the namespace System.Linq.

Linq to Objects is particularly useful when we need to query, filter and/or order an in-memory data collection. These tasks when done without Linq (traditional ways) require quite a lot of code that uses loops and temporary variables. Another advantage on using Linq is that the code is easier to read, maintain and debug, as the code clearly shows what we'll get as result. Look at the example:

string[] Months = {"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"};

var MonthsWithJ =
from mon in Months
where mon.StartsWith("J")
orderby mon descending
select mon;

foreach (var m in MonthsWithJ) {
Console.WriteLine(m);
}


The result will be:

June
July
January


How would we produce the same result without Linq? If you want to have some fun and practice some algorithms, suit yourself :)

Now, let's say if, instead of an array of strings we could query an Object list? Yeah, it's possible:

class Program {

class Person {
public string FirstName { get; set; }
public string LastName { get; set; }
}

static void Main(string[] args) {

var Felipe = new Person { FirstName = "Felipe", LastName = "Guerço" };
var Gerson = new Person { FirstName = "Gerson", LastName = "Motta" };

var People = new List<Person> {Gerson, Felipe};

var qry =
from person in People
orderby person.FirstName
select person;

foreach (var p in qry) {
Console.WriteLine("{0} {1}", p.FirstName, p.LastName);
}
}
}


Now we'll take a little break on Linq to show some of the new C# features for those that doesn't know them yet. First, auto properties:

public string FirstName { get; set; }


This implementation creates the property and, behind the scenes create the encapsulated field to store the property value. Very usefil for those properties that are read and written directly in the fields and don't need any specific validation logic behind them. But, at same time, provide structure to future changes, as the get and set are already there.

Next, type inference

var Felipe = new Person { FirstName = "Felipe", LastName = "Guerço" };


In early versions we had to define the variable type before initialize it. With this new feature the compiler infers the type in the first value assignment. Make no mistake: the type definition is still strong (not variant); we just don't need to explicitly inform the type because the compiler knows it from the assignment. To define a variable without initialize we do need to inform the type.

At last, a special constructor:

var Felipe = new Person { FirstName = "Felipe", LastName = "Guerço" };


This constructor allows us to create an instance of a class setting the properties rigth away.

Now Let's get back to Linq. Here we'll query all people on the list sorting by FirstName. If we wanted, we could add a search criteria by Name adding a where clause:

where person.FirstName.Contains("xxx")


Cool, isn't it? But there's more! We can query related data in more complex collections:


class Program {

class Person {
public string FirstName { get; set; }
public string LastName { get; set; }
}

class Pet {
public string Name { get; set; }
public Person Owner { get; set; }
}

static void Main(string[] args) {

var Felipe = new Person { FirstName = "Felipe", LastName = "Guerço" };
var Gerson = new Person { FirstName = "Gerson", LastName = "Motta" };

var Meg = new Pet { Name = "Meg", Owner = Felipe };
var Rex = new Pet { Name = "Rex", Owner = Gerson };
var Max = new Pet { Name = "Max", Owner = Gerson };
var Nina = new Pet { Name = "Nina", Owner = Felipe };

var Pets = new List<Pet> { Meg, Rex, Max, Nina };

var qry =
from pet in Pets
orderby pet.Owner.FirstName
select new {
OwnerName = pet.Owner.FirstName + ' ' + pet.Owner.LastName,
PetName = pet.Name
};

foreach (var p in qry) {
Console.WriteLine("{0} {1}", p.OwnerName, p.PetName);
}

}
}


Now let's see another new interesting feature: Anonymous types.

select new {
OwnerName = pet.Owner.FirstName + ' ' + pet.Owner.LastName,
PetName = pet.Name
};


Here we define a new type (anonymous because it's defined at same time that we set the properties). Now we have an object with properties named OwnerName and PetName. The compiler automatically infers the properties' types according with their initialization.

Now we're goind to do an aggregation. We'll show the owner and how many pets they have:

var qry2 =
from pet in Pets
group pet by pet.Owner.FirstName + ' ' + pet.Owner.LastName into ownerPets
select new {
Name = ownerPets.Key,
Pets = ownerPets.Count()
};

foreach (var p in qry2) {
Console.WriteLine("{0}'s Pets: {1}", p.Name, p.Pets);
}


Now we created a group in the query counting pets with a key being the Owner's name. In this group we have a property named Key, which represents the information we're grouping. Then we project the group key and the group count in the resultset.

Before we finish, let me point out something: We can use these query results as data sources for data-aware controls, such as GridViews on WinForms or WebForms.

Well, it ended up more lengthy than I expected, but i think that it could show some of the power and usefulness of Linq to Objects technique. Thank you all for the support and see you at the next post. Take care!

Artigo completo (View Full Post)

Acesso a dados com Linq

Click here to see the english version of this post

Olá a todos. Peço desculpas pelo tempo em que estive sem postar aqui no blog. Antes de chegar no assunto gostaria muito de mandar um obrigado especial a todos os visitantes do Estação ZN, que está crescendo em acessos cada vez mais. Nós nos sentimos muito orgulhosos e felizes de ver que este conteúdo que nós postamos aqui e que são freqüentemente retirados de conversas e problemas do dia-a-dia está chegando a todos que acessam nosso blog. Se o que é postado aqui consegue ajudar, fazer pensar, ou até mesmo distrair alguém nosso trabalho já valeu a pena.

Para compensar vou postar sobre um assunto que nos (eu e o Gerson) deixou boquiabertos: Linq - Uma nova tecnologia de acesso a dados presente no Visual Studio 2008 e na .Net 3.5.

Linq é sigla para Language-integrated query. Significa que é uma tecnologia (ou melhor, um conjunto delas) que adiciona recursos de consulta semelhantes às queries da linguagem SQL no nível da linguagem (compilador).

O que isso quer dizer? Que esta tecnologia nos permite (entre outras coisas) consultar dados em memória, arquivos XML e até de bancos de dados relacionais de forma declarativa (funcional), ao invés da maneira imperativa tradicional que usamos.

Linq veio também para diminuir uma coisa chamada "impedance mismatch", que representa a diferença entre o modelo de classes/objetos do software e os modelos de entidades/relacionamentos do banco e dos arquivos XML. Explicando um pouco melhor: Vamos partir do seguinte princício: Dados Relacionais <> XML <> Objetos. No software nós utilizamos o modelo POO, com herança, polimorfismo e por aí vai. Os dados que nossos aplicativos geralmente acessam estão representados em forma de tabelas em bancos de dados relacionais ou arquivos XML. Entre estes três mundos nós não temos praticamente nenhuma compatibilidade; até os tipos de dados são diferentes.
Hoje em dia, para trabalhar com estes dados em nossos aplicativos nós precisamos usar as APIs que as linguagens nos fornecem. Mas nós sempre precisamos escrever mais código que deveríamos, e o código que escrevemos para acessar estes dados não representa claramente o resultado que queremos. Isso se deve à maneira imperativa que as linguagens requerem para acesso aos dados.

Ah, Felipe..., ..., ... Ok. Vamos a um exemplo:

Queremos fazer um select no banco de dados. Há algumas pequenas diferenças entre linguagens, mas a idéia é a mesma:


  • 1. Abre conexão com o banco de dados

  • 2. Cria um objeto para realizar a consulta.

  • 3. Passa a consulta SQL para ele.

  • 4. Executa a consulta e retorna para um objeto que armazena o resutset.

  • 5. Libera os recursos e usa o resultset.



Este modelo nos traz a necessidade de implementar, de forma imperativa, o que o sistema deve fazer em cada momento. Também precisamos escrever código para conexão e execução da query, que não faz parte diretamente da lógica e, por fim, temos que enviar a query para o banco como uma string, onde só saberemos se tem algum erro de sintaxe em tempo de execução. Então, quando o banco retornar os resultados teremos que "traduzir" este resultset em objetos para se encaixar ao nosso modelo de classes do programa. Em resumo: muito código e de difícil leitura, manutenção e depuração.

Mas como o Linq é diferente? Primeiro vamos ver os diversos tipos de formas do Linq. Primeiro temos o Linq to Objects, que nos permite selecionar e ordenar e filtrar coleções em memória. Vamos dar um exemplo:

string[] Meses = {
"Janeiro",
"Fevereiro",
"Março",
"Abril",
"Maio",
"Junho",
"Julho",
"Agosto",
"Setembro",
"Outubro",
"Novembro",
"Dezembro"};

var MesesComA =
from mes in Meses
where mes.StartsWith("A")
orderby mes descending
select mes;

foreach (var m in MesesComA) {
Console.WriteLine(m);
}


Dê uma olhada na parte onde consultamos o array de string Meses. Neste trecho fazemos uma consulta no array Meses onde trazemos qualquer elemento que comece com a letra A e ordenamos o resultado em ordem decrescente. Desta forma acessamos os dados de forma declarativa, assim como nas linguagens funcionais. Imagine como escreveríamos este código na forma imperativa padrão...

Em Linq to Objects, podemos fazer este tipo de consulta em qualquer classe que implemente a interface IEnumerable (o array implementa essa classe, embora não pareça).

Este modelo de queries pode ser aplicado também em dados do banco de dados e arquivos XML. Mas como? Primeiro vamos falar do banco de dados - não vamos nos aprofundar muito porque o objetivo deste post é mostrar o que é Linq e do que ele capaz.

Nós fazemos consultas em bancos de dados da mesma forma declarativa que consultamos coleções de objetos. Mas Felipe, se eu tiver que trazer uma tabela inteira do banco e ter que transformá-la em array para depois fazer a consulta pode jogar esta tecnologia fora! Com certeza a Microsoft não faria isso com uma tecnologia que visa facilitar a vida dos desenvolvedores. O Linq to SQL funciona com uma outra tecnologia da linguagem: Mapeamento de entidades.

Em Linq to SQL nós temos nossos objetos no programa e os decoramos com atributos especiais de mapemento (Em outros posts eu falo e mostro mais sobre isso). De forma mais simples, nós marcamos nossas classes como "Classes de entidade" do banco de dados e informamos as tabelas e campos que nossos objetos/propriedades representam; então, quando consultamos estes objetos, o Linq monta a query para o banco de dados e "traduz" os objetos e propriedades em tabelas e campos. O Linq trata intrinsecamente todos os processos que são necesários mas não fazem parte da lógia do programa, como conexão com o banco, obtenção de registros e tradução de resultsets em objetos.

Linq to SQL vai além disso, provendo também API de atualização de dados, transação e controle de concorrência.

Linq to XML provê uma API simples e única para consultar e também criar arquivos XML; uma API muito mais simples que as atuais que conhecemos (DOM, XSL, XPath, XQuery). A sintaxe de consulta é muito semelhante à Linq to Objects, e esta padronização é muito boa nós desenvolvedores nos acostumarmos rapidamente.

Como o objetivo deste post é falar sobre uma nova tecnologia e ter uma visão geral, vou deixar os "sabores" específicos do Linq para outros posts. Até lá procurem mais e divirtam-se.

Um grande abraço a todos e até a póxima.

Artigo completo (View Full Post)

Data access with Linq

Clique aqui para ver este post em português

Hello everyone. This is the first post in Estação ZN in English. We decided to give an "English version" to our posts due to the increasing non-Brazilian public of our blog, which we would like say thank you very much. From now on I'll try to make an English translation of every post i make. I ain't a native English speaker, so please bear with me a little bit. :)

Let's get started. In this post I'm bringing an issue that left me and Gerson speechless: A new data access technology present in Visual Studio 2008 and .NET 3.5.

Linq stands for Language-integrated Query. It's a technology (a few of them, in fact) that adds query capabilities at language (compiler) level.

What does it mean? It means that Linq allows us (amongst others things) to query in-memory data, XML files and even relational database tables in a declarative manner (like funcional languages) instead of the traditional, imperative way we're used to.

Linq also came to propose a solution for the "impedance mismatch", that is the difference between the program's object model (OOP) and the relational databases/XML files data model. Going a bit deeper: Let's begin with the principle: Relational data <> XML files <> Objects hierarchy/relationships. At the software we have the OOP model, with inheritance, polimorphism and so on. The data our software usually accesses are represented in relational database tables and XML files. In these worlds we have no compatibility whatsoever; even the data types are different.
In order to work with data nowadays we need to use APIs that the languages provide us. But we always have to write more code than we should, and the code that we write to access the data doesn't clearly represent what we want to do. That is because of the imperative way that the languages require to access and manipulate data on external sources.

Eh..., ..., ... Ok. Here's an example:

We want to query data from a database. There are minor differences between the languages but it all comes down to one path in most cases:


  • 1. Open connection with the database

  • 2. Instantiate an object to execute the query

  • 3. Pass the query as string

  • 4. Send the query to the database and get the resultset

  • 5. Release the resources and uses the resultset



This model comes with the necessity of implement, in a imperative way, what the program has to do at each moment. We also have to write code to explicitly connect to the database and run the query, which isn't part of our program logic, and at last, but not least, we have to code the query as string, not using the compiler's type checking at design time - if our query has any errors, we'll discover it only at run time. Then, when the application retrieve the data from the database we have to manually "translate" the database's resultset into objects. It takes too many "unnecessary" code (I would say code that doesn't belong there) and produces code that is difficult to read, mantain and debug.

But how's Linq different? First, let's see the several "flavors" of Linq. We'll see the Linq to Objects first, which allows us to query, filter and sort in-memory collections. Let's go on a example:

string[] Months = {
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"};

var MonthsWithA =
from mon in Months
where mon.StartsWith("A")
orderby mon descending
select mon;

foreach (var m in MonthsWithA) {
Console.WriteLine(m);
}


Take a look at the part where we query the string array Months. In this fragment we search the Months array for any month that starts with the letter A and sort the results descending. This way we access the data in a declarative way, like we would do with funcional languages. Imagine how would be the code to achieve the same results in the traditional, imperative way...

In Linq to Objects we can query any object that implements the IEnumerable interface (the array implenents this interface even though it doens't look like).

This querying model can be applied in relational data and XML files too. But how? Let's see the relational database first - We won't dive too deep into it for now because this post's objective is to show what is Linq and what it is capable of.

With Linq to SQL we can query the database in the same declarative way we do on object collections. But Felipe, if I have to retrieve the entire table from the database and convert it into an array before I can use the Linq, then I surely don't want it! For sure Microsoft wouldn't do it with a technology that is intended to make the developers' life easier. Linq to SQL works with another new language enhancement: Entity Mapping.

In Linq to SQL we have the classes in our program decorated with the special Mapping attributes (I'll talk about and show it in another posts). In other words, we'll "mark" our classes as "Entity classes" and inform which tables and fields are related to which classes and properties; and then, when we query these objects, Linq "mounts" the query and retrieve the results into the objects - all thanks to the mapping attributes.

Linq to SQL can do way more than this. It also provides APIs for data updates, transactions and concurrency control. We'll see more of that later.

Linq to XML provides a simple and unified API to query and also create/edit XML files; an API that is way simpler than those we know nowadays (DOM, XSL, XPath, XQuery). The query syntax is very alike to the Linq to Objects, and this is very nice to us developers to get used to quickly.

As the goal of this post being talk about a relatively new technology and have a peek into all this, I'll let the specific "flavors" of Linq to other posts. See you all and have fun.

Thank you for spending time with us, and please excuse me about any English errors, as i'm no native English speaker, and feel free to send any suggestions and even corrections (please correct me!). Bye...

Artigo completo (View Full Post)

sexta-feira, 27 de abril de 2007

C# - Implementando suporte a eventos na sua classe

Olá novamente a todos. Neste post vou escrever sobre uma técnica interessante e com certeza muito útil no desenvolvimento de componentes - Eventos.

Nas linguagens de programação e IDEs modernas nós trabalhamos com eventos o tempo todo - OnClick do botão, OnChange da caixa de texto, etc...

Vamos fazer um pequeno exemplo. Vou criar uma classe chamada Figura, que representa uma figura com os eixos X, Y e Z.

class Figura {

// eixos da figura
private float eixoX = 0;
private float eixoY = 0;
private float eixoZ = 0;

// contrutor da classe
public Figura(float a, float b, float c) {
eixoX = a;
eixoY = b;
eixoZ = c;
}


// métodos que invertem os eixos
public void InverterX() {
eixoX = -eixoX;
AposInverter("X invertido");
}

public void InverterY() {
eixoY = -eixoY;
AposInverter("Y invertido");
}

public void InverterZ() {
eixoZ = -eixoZ;
AposInverter("Z invertido");
}

// definição do evento AposInverter
public delegate void FigureHandler(string msg);
public static FigureHandler AposInverter;
}

Esta classe (Figura) possui 3 campos de dados (eixoX, eixoY e eixoZ), 3 métodos (InverterX, InveterY e InterterZ) e 1 evento (AposInverter)

Vamos detalhar um pouco a declaração do evento AposInverter:

1. definimos o delegate do método a ser executado para o evento.
Delegate, resumidamente, representa uma chamada à execução de um método. Na linguagem C++ há um recurso parecido chamado callback function, que representa um apontamento (ponteiro) para um método. Em PHP também há um recurso semelhante que eu exemplifiquei neste post. Em C# a implementação é mais elegante e protegida também. O delegate é um tipo em C#; nós temos que definir o delegate em tempo de desenvolvimento.

Vamos rever o delegate:


public delegate void FigureHandler(string msg);


Neste caso o delegate FigureHandler é um método sem retorno (void) que aceita um parâmetro (string msg).

Nos métodos InveterX, InveterY e InverterZ temos o disparo do evento AposInveter informando o que foi invertido. Com isso podemos criar na nossa classe principal uma função que é executada quando este evento acontece, podendo assim agir de acordo com a inversão dos eixos.

Vamos ver a implementação na classe principal:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace DelegatesApp {
public partial class Form1 : Form {

private Figura figura;

public Form1() {
InitializeComponent();

figura = new Figura(10, 20, 30);
Figura.AposInverter += new Figura.FigureHandler(figura_AposInverter);
}

private static void figura_AposInverter(string msg) {
MessageBox.Show(msg);
}

private void button1_Click(object sender, EventArgs e) {
figura.InverterX();
}

private void button2_Click(object sender, EventArgs e) {
figura.InverterY();
}

private void button3_Click(object sender, EventArgs e) {
figura.InverterZ();
}

}
}

Esta classe representa um Windows Form de uma Windows Application em C#.

Primeiro temos um campo privado dla classe figura do tipo Figura (nossa classe criada).
No construtor da classe Form1 criamos uma instância da classe Figura na variável figura e conectamos o método figura_AposInverter ao evento AposInverter da classe Figura

private static void figura_AposInverter(string msg) {
MessageBox.Show(msg);
}

Aqui criamos o método no modelo do manipulador de evento (delegate) da classe.

Então no evento Click dos botões invertemos cada um dos eixos. O comportamento esperado do programa é chamar um MessageBox.Show() a cada inversão de eixo.

Então é isso. Particularmente eu achei muito simples a forma de implementar algo tão útil no desenvolvimento.

Abraços a todos e, como sempre, fiquem à vontade para comentar e participar.

Artigo completo (View Full Post)

sexta-feira, 23 de março de 2007

POO - Polimorfismo

Olá a todos. Este é outro post falando das técnicas de programação orientada a objetos.

Polimorfismo é a técnica que permite implementar um método numa classe que tenha o comportamento diferente do método na sua classe ancestral. Podemos entender como um exemplo um objeto chamado Automóvel, que tem dois descendentes: Carro e Moto.

O Objeto Automóvel tem um método chamado ligar, que todo automóvel possui. Os objetos Carro e Moto também têm o método ligar, porém com implementações diferentes entre si.

Vamos fazer alguns códigos:

Delphi:

interface

type

TAutomovel = class
public
procedure Ligar;
end;


TCarro = class(TAutomovel)
public
procedure Ligar; override;
end;

TMoto = class(TAutomovel)
public
procedure Ligar; override;
end;

implementation

procedure TAutomovel.Ligar;
begin
{implementação do método Ligar da classe TAutomovel}
end;


procedure TCarro.Ligar;
begin
{a palavra chave inherited indica que este método vai incluir a
implementação do método do ancestral no ponto em que foi inserida}
inherited;

{implementação do método Ligar da classe TCarro}
end;


procedure TMoto.Ligar;
begin
{a palavra chave inherited indica que este método vai incluir a
implementação do método do ancestral no ponto em que foi inserida}
inherited;

{implementação do método Ligar da classe TMoto}
end;


Java:

class Automovel {
pubic void ligar() {
// implementação do método ligar da classe Automovel
}
}

class Carro extends Automovel {
public void ligar() {
// o método super() chama a implementação do método da classe
// ancestral no ponto em que foi iserido
super();

// implementação do método ligar da classe Carro
}
}

class Moto extends Automovel {
public void ligar() {
// o método super() chama a implementação do método da classe
// ancestral no ponto em que foi iserido
super();

// implementação do método ligar da classe Moto
}

}


C#

class Automovel {
public void ligar() {
// implementação do método ligar da classe Automovel
}
}

class Carro : Automovel {
public override void ligar() {
// a chamada a base. chama a implementação do método da classe
// ancestral no ponto em que foi iserido
base.ligar();

// implementação do método ligar da classe Carro
}
}

class Moto : Automovel {
public override void ligar() {
// a chamada a base. chama a implementação do método da classe
// ancestral no ponto em que foi iserido
base.ligar();

// implementação do método ligar da classe Moto
}
}


Outra forma de polimorfismo é quando a classe ancestral tem um método mas não faz nenhuma implementação, deixando-a por parte das suas classes descendentes. Este tipo de método é chamado abstrato. Neste caso a classe derivada é obrigada a fazer sua própria implementação do método.

Vou abrir um pequeno parêntesis para falar sobre 'abstratos' em POO.

Geralmente métodos e classes abstratas apenas repredentam a idéia e não a funcionalidade. Vamos a exemplos:

Classes abstratas não podem ser instanciadas.

O quê? Como assim? Por que ter classe se eu não posso instanciá-la?
Uma das principais vantagens de se usar classes abstratas é que nos permite introduzir comportamento comum aos descendentes.

Vamos a um exemplo prático: Figuras geométricas. O que é exatamente uma figura geométrica? Nós não temos uma resposta concreta porque figura geométrica é um objeto abstrato. Mas quanto a quadrado? Retângulo? Losango? Estes são figuras geométricas que podemos descrever claramente.

Todas as figuras geométricas têm um método chamado 'desenhar', mas as implementações são diferentes entre as figuras. É aí que entram a classe abstrata e o método abstrato.

Classes abstratas não podem ser instanciadas. Por um motivo bem simples: Porque são abstratas! Hehe... A classe só tem uma estrutura básica para servir de base para as suas classes descendentes.

Por exemplo, a classe FiguraGeometrica tem o método abstrato Desenhar, que aceita como argumentos as coordenadas de onde ele vai começar a ser desenhado (x e y). Todos os seus descendentes terão este método, mas cada um deles deve ter sua própria implementação.


Delphi

type
TFiguraGeometrica = class
public
procedure Desenhar(const x, y: Integer); virtual;
end;


TQuadrado = class(TFiguraGeometrica)
public
procedure Desenhar(const x, y: Integer); override;
end;

TLosango = class(TFiguraGeometrica)
public
procedure Desenhar(const x, y: Integer); override;
end;

...

procedure MontarFigura(Figura: TFiguraGeometrica; const x, y: Integer);
begin
Figura.Desenhar(x, y);
end;


Java

abstract class FiguraGeometrica {
abstract void desenhar(int x, int y);
}

class Quadrado extends FiguraGeometrica {
public void desenhar(int x, int y) {
// implementação do método desenhar do objeto Quadrado
}
}

class Losango extends FiguraGeometrica {
public void desenhar(int x, int y) {
// implementação do método desenhar do objeto Losango
}
}


...

void montarFigura(FiguraGeometrica figura, int x, int y) {
figura.desenhar(x, y);
}


C#

abstract class FiguraGeometrica {
public abstract void desenhar(int x, int y);
}


class Quadrado : FiguraGeometrica {
public override void desenhar(int x, int y) {
// implementação do método desenhar do objeto Quadrado
}
}

class Losano : FiguraGeometrica {
public override void desenhar(int x, int y) {
// implementação do método desenhar do objeto Losango
}
}


...

public void montarFigura(FiguraGeometrica figura, int x, int y) {
figura.desenhar(x, y);
}


Mas Felipeeee... que efeito prático isso vai ter na aplicação?

Desta forma nós evitamos redundância no nosso código, 'if' que não precisamos... Quando executamos o método MontarFigura nós passamos qualquer objeto derivado da classe FiguraGeometrica que, pelo fato dela ser abstrata (virtual em delphi) ela vai executar o método da classe derivada correspondente. Maneiro, né...

Esse post acabou sendo mais longo que eu esperava, mas espero que o conteúdo postado tenha sido bem absorvido. Abraços.

Artigo completo (View Full Post)

 
BlogBlogs.Com.Br