Академический Документы
Профессиональный Документы
Культура Документы
ndice
Acesso a Dados com ADO.NET ..................................................................................................... 3
Ado.net ............................................................................................................................................ 3
Principais classes do ADO.NET ................................................................................................. 4
DataSource .............................................................................................................................. 4
SQLConnection ....................................................................................................................... 5
SQLCommand ......................................................................................................................... 6
SQLDataReader ...................................................................................................................... 6
Parmetros ............................................................................................................................... 7
SQLDataAdapter , DataSet e DataTable ................................................................................. 8
SQLTransaction ...................................................................................................................... 9
Generics ......................................................................................................................................... 10
Nullable Types .......................................................................................................................... 11
Mtodos Annimos ................................................................................................................... 12
Actions ...................................................................................................................................... 12
Predicates .................................................................................................................................. 13
Comparison ............................................................................................................................... 14
Converter ................................................................................................................................... 15
Inference Types ......................................................................................................................... 16
Object Initializers ...................................................................................................................... 17
Anonymous Types..................................................................................................................... 18
Extension Methods .................................................................................................................... 18
Implicitly Typed Arrays ............................................................................................................ 19
Lambda Expressions ................................................................................................................. 19
LINQ ............................................................................................................................................. 22
Usando LINQ em Collections ................................................................................................... 22
Usando o operador ORDER BY ............................................................................................... 23
Querys em Tipos Estruturados .................................................................................................. 23
Escrevendo consultas em LINQ ................................................................................................ 24
Filtrando pela mdia: ............................................................................................................. 25
Para Ordemenar os resultados ............................................................................................... 25
Para criar um campo calcumado ........................................................................................... 26
LINQ To SQL ............................................................................................................................... 27
Incluindo um novo registro ....................................................................................................... 27
Alterando o registro ................................................................................................................... 28
Excluindo o registro .................................................................................................................. 28
Threading ...................................................................................................................................... 29
CPU vs. I/O Bound.................................................................................................................... 29
A classe Thread ......................................................................................................................... 29
ThreadPool ................................................................................................................................ 31
Fazendo chamadas thread-safe para controles Windows Forms ............................................... 33
Chamadas para um Controle do Windows que no so thread-safe ..................................... 33
Chamadas thread-safe para um Controle de formulrios do Windows ................................. 34
Chamadas thread-safe com BackgroundWorker ................................................................... 35
BackgroundWorker ............................................................................................................... 35
Manipulando XML com C# .......................................................................................................... 38
EXEMPLO DE XML ................................................................................................................ 38
Criao do Arquivo xml ............................................................................................................ 38
Treinar Cursos e Treinamentos
C# 2008 - Mdulo II
C# 2008 - Mdulo II
Ado.net
O ADO.NET foi criado para ser um modelo de dados desconectado, pronto para Web.
formando por uma srie de objetos, alguns independentes de fonte de dados, outros
no. Um objeto independe de fonte pode abrigar ao mesmo tempo dados de origens
diversas, como por exemplo, uma tabela de um banco de dados Oracle e outra de um
arquivo Access.
O Objeto de conexo para o SQLSever o SQLConnection. Havendo uma conexo os
dados podem ser recuperados para um SQLDatareader, SQLCommand ou mesmo um
DataSet.
O SQLCommand permite executar um comando SQL contra uma fonte de dados. Pode
trabalhar apenas com um SQLConnection ou em conjunto com outras classes
ADO.NET.
Um SQLDataReader um cursor unidirecional e somente leitura. timo para leitura de
dados ou gerao de relatrios, pois veloz. Porm no permite qualquer alterao nos
dados, alm de monopolizar a conexo com o banco de dados enquanto esta operando.
Um DataSet um pequeno banco de dados em memria. Voc no precisa de uma
conexo permanente com o banco de dados enquanto estiver utilizando os dados. Voc
pode abrir a conexo, recuperar os dados, executar alteraes, excluses ou incluses,
abrir novamente a conexo e atualizar a fonte de dados. Dentro de uma DataSet
podemos ter uma ou mais DataTables, que so tabelas, que podem ter origens de
fontes de dados independentes. Podemos ainda ter DataRelations, que representam
relaes entre tabelas. Uma DataTable formado por DataRows, que representam
colunas. Outra classe importante DataView, que exatamente o que parece: Uma
viso de dados. Um DataTable possui um DataView padro, outros podem ser criados.
Todos os objetos descritos neste pargrafo so independentes da fonte dos dados, pois
so armazenados em memria no formato XML.
Treinar Cursos e Treinamentos
C# 2008 - Mdulo II
Agora como transformar dados de uma fonte especifica em um DataSet? Esta tarefa
do SQLDataAdapter , que faz a transformao dos dados entre a sua origem, atravs
da conexo, at o DataSet e vice-versa. O SQLDataAdapter devolve a conexo no
estado que a encontrou: Se estava aberta, mantm aberta. Se estava fechado, abre,
executa a operao e fecha a conexo.
DataSource
Embora existam provedores para acessar as mais variadas fontes de dados, iremos
demostrar as funcionalidades do ADO.NET com classes de acesso ao SQLServer. A
funcionalidade das demais classes bem semelhante.
A classe DataSource uma classe que nos permite acessar diversos bancos de dados
relacionais ou no, e que internamente utiliza diversos objetos do ADO.NET, tornando o
seu uso mais simples atravs de um nico objeto. Por exemplo, para retornar um
conjunto de dados de um SQLServer, voc precisar no mnimo de um SQLConnection,
um SQLCommand e um SQLDataReader. Por outro lado, voc pode obter o mesmo
Treinar Cursos e Treinamentos
C# 2008 - Mdulo II
SQLConnection
Para utilizar as classes ADO.NET para SQL Server, voc deve importar o namespace
system.data.sqlclient. Para as classes independentes de fonte de dados, como o
DataSet, o namespace sytem.data
O SQLConnection representa uma conexo com um banco de dados SQLServer. Suas
principais propriedades so ConnectionString, que a string com os parmetros de
conexo com o servidor. Entre os mtodos temos Open, que abre a conexo, e close,
que fecha a mesma. A propriedade State retorna o estado atual da conexo. Vejamos o
exemplo abaixo:
SqlConnection Conexao = new SqlConnection();
Conexao.ConnectionString
=
"Data
Source=LOCALHOST\\SQLEXPRESS;
Catalog=AdventureWorks; Integrated Security=True";
Conexao.Open();
//Executa algum cdigo
Conexao.Close();
Initial
A abertura da conexo deve ser protegida em um bloco try...catch, j que ao abrir uma
conexo, o servidor pode no estar disponvel, a string de conexo pode estar errada, o
usurio pode no ter permisso de acesso, etc.
C# 2008 - Mdulo II
SQLCommand
A classe SQLCommand permite que seja executado qualquer comando SQL.
propriedade CommandText: instruo SQL, de um nome de tabela ou procedure.
propriedade Connection: Conexo vlida com o banco de dados.
A execuo do comando pode ser feito atravs de trs mtodos distintos:
SQLDataReader
O SQLDataReader um cursor unidirecional e somente leitura, porm muito veloz.
Voc pode ligar seu resultado diretamente a um controle:
SqlCommand comando = new SqlCommand();
comando.Connection = Conexao;
comando.CommandText = "SELECT CurrencyCode,Name FROM Sales.Currency";
SqlDataReader reader = comando.ExecuteReader();
GridView1.DataSource = reader;
Neste outro exemplo, ele ligado a um DropDownList. Note que nome da moeda
ligado a propriedade TextField, enquanto o cdigo a propriedade Valuefield, desta forma
ser exibida a nome da moeda para o usurio, mas programaticamente poderemos
facilmente recuperar o cdigo da moeda selecionada:
SqlCommand comando = new SqlCommand();
comando.Connection = Conexao;
comando.CommandText = "SELECT CurrencyCode, Name FROM Sales.Currency";
SqlDataReader reader = comando.ExecuteReader();
DropDownList1.DataSource = reader;
DropDownList1.DataValueField = "CurrencyCode";
DropDownList1.DataTextField = "Name";
C# 2008 - Mdulo II
Parmetros
A utilizao das classes de parametros do ADO.NET um ponto importante no quesito
segurana, pois eliminam o risco de injeo de SQL. A classe parmetros permite que
sejam criados parmetros para a execuo de instrues sql. Na instruo o parmetro
deve ser identificado por @ mais um identificador nico. O objeto parmetro dever ter
o mesmo nome o qual vai passar o valor.
SqlCommand comando = new SqlCommand();
comando.Connection = Conexao;
comando.CommandText = "SELECT CurrencyCode,Name FROM Sales.Currency";
SqlParameter parametro = new SqlParameter("@ContactID", SqlDbType.Int);
parametro.Value = Convert.ToInt32("1");
comando.Parameters.Add(parametro);
SqlDataReader reader =
comando.ExecuteReader(CommandBehavior.CloseConnection);
GridView1.DataSource = reader;
C# 2008 - Mdulo II
A atualizao dos dados feita atravs do mtodo update. Apenas quando o mtodo
executado que qualquer alterao nos dados sero replicados ao banco de dados.
Outro aspecto importante que o para fazer uma atualizao, seja excluso, incluso
ou alterao, o Adapter precisa obter os comando SQL para tais operaes. Atravs da
classe CommadBuilder podemos gerar automaticamente estas instrues para o
SQLDataAdapter.
SqlDataAdapter Adp = new SqlDataAdapter
("SELECT
*
FROM
Person.Contact
SqlCommandBuilder CmdBuilder = new SqlCommandBuilder;
DataSet Ds = new DataSet();
Ds.Tables[0].Rows[0]["FistName"] = "Frederico";
Adp.Update(Ds);
",
Conexao);
C# 2008 - Mdulo II
SQLTransaction
O ADO.NET tambm possui classes que do suporte a controle de transaes.
Devemos declarar uma transao e inici-la pelo objeto de conexo e ainda atribu-la
aos objetos que faro parte da operao. Para confirmar as operaes chamamos o
mtodo commit do objeto Transaction, para desfazer o mtodo rollback.
SqlTransaction Trans = Conexao.BeginTransaction();
SqlDataAdapter Adp = new SqlDataAdapter
("SELECT * FROM Sales.Currency ", Conexao);
Adp.InsertCommand.Transaction = Trans;
SqlCommandBuilder CmdBuilder = new SqlCommandBuilder(Adp);
DataTable Dt = new DataTable();
Adp.Fill(Dt);
DataRow Dr = Dt.NewRow();
Dr["CurrencyCode"] = "BRU";
Dr["Name"] = "Brazilian UNReal";
Dr["ModifiedDate"] = "01/01/2006";
Dt.Rows.Add(Dr);
try {
Adp.Update(Dt);
Trans.Commit();
}
catch (Exception s)
{
Trans.Rollback();
}
C# 2008 - Mdulo II
10
Generics
Generics um novo conceito introduzido na verso 2.0 do .NET Framework, como parte
integrante do CLS (Common Language Specification). Generics permitem termos
classes, mtodos, propriedades, delegates e Interfaces que trabalhem com um tipo no
especificado. Esse tipo "no especificado" quer dizer que estes membros trabalharo
com os tipos que voc especificar em sua construo.
Como j sabemos, o ArrayList permite adicionarmos qualquer tipo dentro dele. Mas e se
quisssemos apenas adicionar valores inteiros, ou somente strings? Isso no seria
possvel pois o mtodo Add aceita um System.Object. Com Generics, possvel criar
colees de um determinado tipo, o que permitir que o usurio somente adicione
objetos do mesmo tipo e, se por acaso ele quiser adicionar algo incompatvel, o erro j
detectado em design-time. Classes genricas oferecem vrias vantagens, entre elas:
Reusabilidade: Um simples tipo genrico pode ser utilizado em diversos cenrios.
Um exemplo uma classe que fornece um mtodo para somar dois nmeros. S
que estes nmeros podem ser do tipo Integer, Double ou Decimal. Com o
Generics, no precisaramos de overloads do mtodo Somar(...). Bastaria criar
um nico mtodo com parmetros genricos e a especificao do tipo a ser
somado fica a cargo do consumidor.
Type-safety: Generics fornecem uma melhor segurana, mais especificamente
em colees. Quando criamos uma coleo genrica e especificamos em seu
tipo uma string, somente podemos adicionar strings, ao contrrio do ArrayList.
Performance: Fornecem uma melhor performance, j que no h mais o boxing e
unboxing. Alm disso, o nmero de converses cai drasticamente, j que tudo
passa a trabalhar com um tipo especificado, o que evita transformarmos em outro
tipo para termos acesso s suas propriedades, mtodos e eventos.
Uma classe que aceita um tipo em sua declarao pode trabalhar internamente com
este tipo. Isso quer dizer que os mtodos podem aceitar em seus parmetros objetos do
tipo especificado na criao da classe, retornar esses tipos em propriedades, etc.
Para exemplificarmos, vejamos uma classe que aceita um valor genrico, o que quer
dizer que ela pode trabalhar com qualquer tipo: atravs do exemplo abaixo "T" que
identifica o tipo genrico que j pode ser acessado internamente pela classe.
public class ClasseGenerica<T>
{
private T _valor;
public T Valor
{
get
{
return this._valor;
}
set
{
this._valor = value;
}
}
10
C# 2008 - Mdulo II
11
}
//Utilizao:
ClasseGenerica<string> classe1 = new ClasseGenerica<string>();
classe1.Valor = ".NET";
ClasseGenerica<int> classe2 = new ClasseGenerica<int>();
classe2.Valor = 123;
O que diferencia uma classe normal de uma classe genrica o tipo que devemos
especificar durante a criao da mesma. O valor "T" pode ser substitudo por qualquer
palavra que voc achar mais conveniente para a situao e, quando quiser referenciar o
tipo genrico em qualquer parte da classe, poder acess-lo como um tipo qualquer,
como um Integer e felizmente, o Intellisense d suporte completo a Generics. Digamos
que sua classe somente trabalhar com Streams, ento poderia definir "T" como
"TStream" (se assim desejar):
public class ClasseGenerica<TStream>
{
//....
}
Como podemos notar no exemplo, a classe1 trabalha somente com valores do tipo
string. J a classe2 somente trabalha com valores do tipo inteiro. Mesmo que quiser
adicionar um tipo incompatvel, o erro j informado em design-time. Mas os Generics
no param por aqui. Existem muitas outras possibilidades para tornarmos os Generics
ainda mais poderosos, como por exemplo critrios (constraints), criao de mtodos
genricos, delegates, Interfaces, entre outros.
Nullable Types
Qualquer tipo-valor em .NET possui sempre um valor padro. Isso quer dizer que ele
nunca poder ter um valor nulo. Um exemplo a estrutura DateTime. Ela tem um valor
padro que 01/01/0001 00:00:00. Apesar de estranha, uma data vlida.
Muitas vezes podemos ter uma data no informada, como por exemplo um objeto
Funcionario que tem uma propriedade chamada DataDemissao. Se este funcionrio no
foi demitido, como conseguiremos distinguir se essa data vlida ou no?
System.Nullable<T> uma estrutura de dados genrica que aceita como tipo qualquer
outro tipo, desde que esse tipo seja outra estrutura (tipo-valor), como por exemplo:
Int32, Double, DateTime, etc.. Atravs deste tipo especial podemos definir valores nulos
para ele, como por exemplo:
Nullable<DateTime> dataDemissao = null;
11
C# 2008 - Mdulo II
12
Mtodos Annimos
Os mtodos annimos nos permitem omitir o mtodo que ser executado quando o
delegate for invocado. Depois de compilado, o compilador se encarrega de criar o
mtodo e, se preocupa em definir todas as referncias para invoc-lo corretamente.
Isso evitar a criao de um mtodo exclusivo para a realizao desta tarefa. Se o
mtodo for utilizado somente naquele local, ento podemos omitir a criao do mtodo
atravs da seguinte sintaxe:
class Program
{
static void Main(string[] args)
{
List<Usuario> users = new List<Usuario>();
users.Add(new Usuario("Adilson"));
users.Add(new Usuario("Rubens"));
users.Add(new Usuario("Sheila "));
users.Add(new Usuario("Silvia"));
users.ForEach(new Action<Usuario>(delegate(Usuario user)
{
Console.WriteLine(user.Nome);
}));
}
}
Actions
Action trata-se de um delegate que foi introduzido dentro da verso 2.0 do .NET
Framework que representa um mtodo que executa uma ao em um objeto especfico.
Trata-se de um delegate genrico que no possui nenhum retorno. Esse delegate e os
delegates que veremos a seguir so comumente utilizandos em conjunto com arrays,
evitando a necessidade da criao de um mtodo exclusivo para iterar pela respectiva
coleo efetuando alguma tarefa para cada um dos seus itens que esto contidos
dentro dela. Se analisarmos a classe Array veremos vrios mtodos que recebem como
parmetros delegates do tipo Actions, Predicates, Comparison e Converter.
Para exemplificar, utilizamos o mtodo ForEach da classe List que aceita como
parmetro um delegate do tipo Action que deve referenciar o mtodo que ser
executado para cada um dos itens da coleo. bom lembrar que o delegate Action
trata-se de um delegate genrico e o tipo a especificar neste cenrio deve,
obrigatoriamente, ser o mesmo tipo que foi especificado na criao do objeto List. Como
exemplo criarei tambm uma classe chamada Usuario que ser utilizada pelos
exemplos durante esta seo:
public class Usuario
{
private string _nome;
public Usuario(string nome)
{
this._nome = nome;
}
12
C# 2008 - Mdulo II
13
Predicates
Os Predicates trabalham de forma semelhante ao Action, com a exceo de que ao
invs de ser um void ele retorna um valor booleano. O Predicate representa um mtodo
que define alguns critrios, determinando se um objeto atende ou no a estes critrios
estabelecidos pelo Predicate. Atravs do exemplo abaixo, utilizamos o mtodo Find da
classe List que, dado um Predicate, ele analisa se o usurio est ou no contido dentro
da listagem e, se estiver, a instncia deste usurio ser atribuda a varivel busca.
class Program
{
static void Main(string[] args)
{
List<Usuario> users = new List<Usuario>();
users.Add(new Usuario("Adilson"));
users.Add(new Usuario("Rubens"));
users.Add(new Usuario("Sheila "));
users.Add(new Usuario("Silvia"));
Usuario busca = users.Find(new Predicate<Usuario>(Search));
if (busca != null)
Console.WriteLine(busca.Nome);
}
private static bool Search(Usuario user)
13
C# 2008 - Mdulo II
14
{
return user.Nome == "Adilson";
}
}
Sintaxe in-line:
class Program
{
static void Main(string[] args)
{
List<Usuario> users = new List<Usuario>();
users.Add(new Usuario("Adilson"));
users.Add(new Usuario("Rubens"));
users.Add(new Usuario("Sheila "));
users.Add(new Usuario("Silvia"));
Usuario busca = users.Find(new Predicate<Usuario>
(delegate(Usuario user)
{
return user.Nome == "Adilson";
}));
if (busca != null)
Console.WriteLine(busca.Nome);
}
}
Comparison
Este delegate representa um mtodo que utilizado para comparar dois tipos. Ele
geralmente utilizado em conjunto com o mtodo Sort da classe fornecida pelo array, que
permite ordenar uma coleo de forma ascendente ou descendente. importante
lembrar que o mtodo Sort no retorna nenhum valor, apenas um void que manipula
os itens internos ao array. Atravs do exemplo abaixo, utilizamos um Comparer padro
para ordenar os usurios que esto contidos dentro da coleo:
class Program
{
static void Main(string[] args)
{
List<Usuario> users = new List<Usuario>();
users.Add(new Usuario("Adilson"));
users.Add(new Usuario("Rubens"));
users.Add(new Usuario("Sheila "));
users.Add(new Usuario("Silvia"));
users.Sort(new Comparison<Usuario>(Sort));
users.ForEach(new Action<Usuario>(Write));
}
private static int Sort(Usuario u1, Usuario u2)
{
return Comparer<string>.Default.Compare(u1.Nome, u2.Nome);
}
private static void Write(Usuario user)
{
14
C# 2008 - Mdulo II
15
Console.WriteLine(user.Nome);
}
}
Sintaxe in-line:
class Program
{
static void Main(string[] args)
{
List<Usuario> users = new List<Usuario>();
users.Add(new Usuario("Adilson"));
users.Add(new Usuario("Rubens"));
users.Add(new Usuario("Sheila "));
users.Add(new Usuario("Silvia"));
users.Sort(new Comparison<Usuario>(
delegate(Usuario u1, Usuario u2)
{
return Comparer<string>.Default.Compare(
u1.Nome, u2.Nome);
}));
users.ForEach(new Action<Usuario>(delegate(Usuario u)
{
Console.WriteLine(u.Nome);
}));
}
}
Converter
A classe List possui um mtodo chamado ConvertAll que recebe como parmetro um
delegate do tipo Converter. Este um delegate genrico que devemos especificar qual
ser o tipo de dado de entrada e de sada em que o mtodo ConvertAll dever converter
cada um dos elementos contidos dentro da coleo. Esse mtodo retornar um novo
objeto List onde cada um dos elementos desta coleo ser do tipo especificado na
criao do delegate Converter. O exemplo abaixo ilustra esse processo, onde
especificamos que a coleo de objetos Usuarios ser convertida para uma coleo de
strings, contendo apenas o nome de cada um deles.
class Program
{
static void Main(string[] args)
{
List<Usuario> users = new List<Usuario>();
users.Add(new Usuario("Adilson"));
users.Add(new Usuario("Rubens"));
users.Add(new Usuario("Sheila "));
users.Add(new Usuario("Silvia"));
List<string> nomes = users.ConvertAll<string>(
new Converter<Usuario, string>(Conversao));
nomes.ForEach(new Action<string>(Write));
}
15
C# 2008 - Mdulo II
16
Sintaxe in-line:
class Program
{
static void Main(string[] args)
{
List<Usuario> users = new List<Usuario>();
users.Add(new Usuario("Adilson"));
users.Add(new Usuario("Rubens"));
users.Add(new Usuario("Sheila "));
users.Add(new Usuario("Silvia"));
List<string> nomes = users.ConvertAll<string>(
new Converter<Usuario, string>(delegate(Usuario user)
{
return user.Nome;
}));
nomes.ForEach(new Action<string>(delegate(string nome)
{
Console.WriteLine(nome);
}));
}
}
Inference Types
As inferncias de tipo ou tipos implcitos so uma exclusividade da verso 3.5 do .NET
Framework. Esta funcionalidade permite ocultarmos a declarao do tipo da varivel
durante a escrita do cdigo. Mas no pense que isso ir tornar a varivel do tipo
System.Object; ao invs disso, o tipo que a varivel ter ser definido a partir do valor
com o qual voc a inicializa. Sendo assim, podemos passar a declarar as variveis da
seguinte forma:
var id = 123;
var nomes = new string[] {"Israel", "Claudia", "Juliano"};
var valor = 12.0;
Ao declarar as variveis desta forma, em design-time voc j ter suporte aos membros
do tipo que voc inicializou a mesma. Para comprovar que o tipo da varivel ir
depender exclusivamente do valor a ela definida, podemos visualizar o cdigo
compilado, que ser algo mais ou menos como o que mostrado logo abaixo:
Treinar Cursos e Treinamentos
16
C# 2008 - Mdulo II
17
int id = 123;
string[] nomes = new string[] {"Israel", "Claudia", "Juliano"};
double valor = 12.0;
Object Initializers
Os inicializadores de objetos consiste em uma seqncia de membros inicializada, que
devem estar entre { } (chaves), onde cada uma das propriedades so separadas por
vrgulas. Para que cada propriedade seja inicializada voc deve especificar o nome da
mesma e, depois do sinal de igual, definir o seu respectivo valor. importante dizer que
voc pode inicializar os membros independente de qual tipo ele seja. O exemplo abaixo
ilustra como devemos proceder para utilizar esse recurso:
public class Usuario
{
public int Id;
public string Nome;
}
//Utilizao
Usuario user = new Usuario() { Id = 1, Nome = "Israel" };
17
C# 2008 - Mdulo II
18
Anonymous Types
Os tipos annimos nos permitem criar um tipo, sem explicitamente criar uma classe
formal para o mesmo. Esse recurso extremamente importante na utilizao do LINQ,
O cdigo abaixo mostra a sintaxe de como podemos criar um objeto com duas
propriedades e, logo aps a sua criao, j podemos acessar as propriedades recm
definidas para o tipo annimo:
var u = new { Nome = "Israel", Idade = 25 };
Console.WriteLine(u.Nome);
Extension Methods
Os extension methods so mtodos estticos que nos permitem incluir estes mtodos
a tipos pr-existentes e que podem ser invocados a partir das instncias desses tipos.
Para exemplificar, podemos adicionar um mtodo rotineiro ao tipo string e assim
utilizarmos por toda a aplicao.
A declarao destes mtodos deve ser dentro de uma classe esttica, sem nenhum
atributo definido. O que vai definir explicitamente o tipo onde este mtodo ser "includo"
o primeiro parmetro deste mtodo que est criando. Os parmetros que vem a seguir
so utilizados para informar um parmetro qualquer que necessrio para que este
extension method possa realizar o seu trabalho. O cdigo abaixo ilustra como cri-los:
public static class Helper
{
public static string RetStrFmt(this string s, string label)
{
return label + ": " + s;
}
public static string RetIntFmt(this int i, string label)
{
return label + ": " + i.ToString();
}
}
//Utilizao
string nome = "Fred";
nome.RetStrFmt("Nome");
int Val = 3;
Val.RetIntFmt("Valor");
O primeiro parmetro (que especifica o tipo em que o mtodo ser "includo") deve estar
Treinar Cursos e Treinamentos
18
C# 2008 - Mdulo II
19
pr-fixado com a keyword this. Como podemos notar no exemplo acima, ao definir o
extension method voc j o tem disponvel no Intellisense, com um cone diferente em
relao ao cone padro de um mtodo qualquer do tipo.
Podemos combinar essa funcionalidade com algumas das funcionalidades acima, que
so os tipos annimos e os inicializadores de objetos e tornar o cdigo um pouco mais
performtico. Em um primeiro momento, talvez um pouco estranho, mas com a
utilizao em nosso dia a dia veremos a produtividade e eficcia que isso nos
proporciona. O exemplo abaixo cria um array onde em cada um dos elementos so
adicionados um tipo annimo:
var pessoas = new[]{
new {
Nome = "Israel",
Idade = 25
},
new {
Nome = "Claudia",
Idade = 23
}
};
Lambda Expressions
Na verso 2.0 do Visual C# a Microsoft introduziu um conceito chamado mtodos
annimos. Os mtodos annimos permitem escrevermos uma "expresso" de forma "inline" em locais onde uma instncia de um delegate esperada. Apesar de citarmos
alguns exemplos acima, vamos analisar um exemplo de mtodo annimo. Supondo que
temos um delegate que recebe dois nmeros inteiros e retorna um valor, tambm
inteiro, temos as seguintes formas de proceder para executar o delegate nas verses
.NET 1.x e 2.0 do .NET:
delegate int Operacao(int a, int b);
//Utilizando a verso 1.x
static void Main(string[] args)
{
Operacao op = new Operacao(Soma);
Console.WriteLine(op(2, 4));
19
C# 2008 - Mdulo II
20
}
public static int Soma(int a, int b)
{
return (a + b) * 3;
}
Como podemos notar, com a verso 2.0 do Visual C#, o mtodo para qual aponta o
delegate no existe mais. Muitas vezes, crivamos um mtodo exclusivamente para
utilizar em conjunto com o delegate, poluindo a classe.
J as Lambda Expressions tornam os mtodos annimos muito mais concisos mas,
pode parecer confuso em um primeiro momento. Essa uma das principais
funcionalidades que o LINQ utiliza em suas query expressions, fornecendo uma forma
compacta e fortemente tipada de escrever funes, passar seus respectivos
argumentos e, efetivamente, a sua avaliao (implementao).
Para exemplificar, vamos analisar como fica o cdigo acima utilizando as Lambda
Expressions:
delegate int Operacao(int a, int b);
static void Main(string[] args)
{
Operacao op = (a, b) => (a + b) * 3;
Console.WriteLine(op(2, 4));
}
20
C# 2008 - Mdulo II
21
21
C# 2008 - Mdulo II
22
LINQ
LINQ (Language Integrated Query) uma nova forma de realizar pesquisas em
conjuntos de dados, sejam relacionais ou no. A idia utilizar uma sintaxe muito
semelhante sintaxe SQL para realizar pesquisas em bloco de informaes, filtrando os
dados quando necessrio atravs da associao de operadores.
Alm da possibilidade de execuo de querys em blocos de informao, objetos e
bancos de dados, uma extenso denominada XLinq foi criada para uso em objectos
XML. A facilidade de uso, permite que instrues XPath e XQuery sejam executadas de
maneira semelhante s instrues SQL.
Um simples array de inteiros foi criado e alguns nmeros foram atribudos como valores.
Note que existem nmeros pares e mpares. Nosso objetivo separar os nmeros
Treinar Cursos e Treinamentos
22
C# 2008 - Mdulo II
23
23
C# 2008 - Mdulo II
using System.Text;
namespace ExLinq
{
class Pessoa
{
private string _nome = "";
private int _idade = 0;
public string Nome
{
get { return _nome; }
set { _nome = value; }
}
public int Idade
{
get { return _idade; }
set { _idade = value; }
}
}
}
System;
System.Collections.Generic;
System.Linq;
System.Text;
namespace ExLinqConsole
{
public class Estudante
{
public string Nome { get; set; }
24
24
C# 2008 - Mdulo II
public string SobreNome { get; set; }
public int Codigo { get; set; }
public List<int> Notas;
}
class Program
{
static void Main(string[] args)
{
List<Estudante> classe = new List<Estudante>()
{
new Estudante(){ Codigo=1,
Nome="Frederico",
SobreNome="Almeida",
Notas=new List<int>(){9,8,9,8}},
new Estudante(){ Codigo = 2,
Nome="Rubia",
SobreNome="Goulart",
Notas=new List<int>(){7,6,8,10}},
new Estudante(){ Codigo = 3,
Nome="Joo",
SobreNome="Almeida",
Notas=new List<int>(){5,6,4,7}}
};
}
}
}
25
25
C# 2008 - Mdulo II
26
26
C# 2008 - Mdulo II
27
LINQ To SQL
LINQ to SQL uma implementao especfica do LINQ para o SQL Server que converte
consultas escritas em C# ou Visual Basic em SQL dinmico , provendo uma interface
que permite mapear os objetos do banco de dados gerando as classes para realizar as
operaes usando a sintaxe LINQ; tambm permite realizar alteraes nos objetos e
atualizar o banco de dados.
Crie um novo projeto Windows Forms
Adicione uma classe LINQ TO SQL
Mova as tabelas do banco ExCadastro como feito com o DataSet
27
C# 2008 - Mdulo II
orderby clientes.nom_cliente
select clientes;
Alterando o registro
Coloque um boto no formulrio e escreva o seguinte cdigo no evento click.
CadastroDataContext db = new CadastroDataContext();
var c = (from cli in db.tb_clientes
where cli.cod_cliente = 1
select cli).Single<tb_cliente>();
c.nom_cliente = "Novo nome";
db.SubmitChanges();
this.dataGridView1.DataSource =
from clientes in db.tb_clientes
orderby clientes.nom_cliente
select clientes;
Excluindo o registro
Coloque um boto no formulrio e escreva o seguinte cdigo no evento click.
CadastroDataContext db = new CadastroDataContext();
var c = (from cli in db.tb_clientes
where cli.cod_cliente = 1
select cli).Single<tb_cliente>();
db.tb_clientes.DeleteOnSubmit(c);
db.SubmitChanges();
this.dataGridView1.DataSource =
from clientes in db.tb_clientes
orderby clientes.nom_cliente
select clientes;
28
28
C# 2008 - Mdulo II
29
Threading
Threads permitem aumentar consideravelmente a performance das aplicaes
delegando os processamentos em diversas unidades de execuo, aumentando a
capacidade de processamento de uma aplicao. No entanto, utilizando de forma
errada, poder piorar ao invs de melhorar, consumindo mais recursos do que o
necessrio, tendo um comportamento inesperado e retornando valores diferentes do
esperado.
O .NET Framework fornece vrias classes que podemos utilizar para criao e
gerenciamento de threads, bloqueio de recursos em um ambiente multi-threading e
sincronizao. Vale dizer que cada tecnologia (Windows Forms, ASP.NET, WCF, etc.)
tem suas peculiaridades em relao a execuo dos mesmos. Essas peculiaridades
definem a caracterstica das aplicaes desenvolvidas sob alguma dessas tecnologias,
adotando uma melhor estratgia para a execuo das mesmas, tirando o mesmo
proveito possvel em um ambiente multi-threading.
A classe Thread
A classe Thread refere-se a uma unidade lgica de execuo. Essa classe fornece
diversas propriedades para que o desenvolvedor possa iniciar, suspender, pausar e
controlar o status, prioridade, etc. Estas classes esto dentro do namespace
System.Threading.
Ao criar uma instncia da classe Thread, voc obrigatoriamente precisa informar qual o
mtodo que ela dever processar, ou melhor, qual tarefa ele dever executar. Esse
vnculo se faz atravs de um dos seguintes delegates:
using System;
using System.Threading;
29
C# 2008 - Mdulo II
30
namespace ExThread
{
class Program
{
static void Main(string[] args)
{
Thread t1 = new Thread(
new ThreadStart(IniciaProcesso));
t1.Name = "Proc 1";
Thread t2 = new Thread(
new ParameterizedThreadStart(IniciaProcesso));
t2.Name = "Proc 2";
Console.WriteLine("Iniciando");
t1.Start();
t2.Start("Teste");
Console.WriteLine("Aguardando");
Console.ReadLine();
}
public static void IniciaProcesso()
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(500);
Console.WriteLine("Thread 1 " + " " +
Thread.CurrentThread.Name + " " +
DateTime.Now.ToString("HH:mm:ss"));
}
}
public static void IniciaProcesso(object value_)
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(1000);
Console.WriteLine("Thread 2 " + value_ + " " +
Thread.CurrentThread.Name + " " +
DateTime.Now.ToString("HH:mm:ss"));
}
}
}
}
Propriedades:
Name
Priority
30
C# 2008 - Mdulo II
31
ThreadState
Mtodos
Start
Abort
Uma vez que o processo inicia voc pode abort-lo atravs do mtodo
Abort da instncia da classe Thread.
Sleep
Join
ThreadPool
A Microsoft disponibilizou um pool de threads, que basicamente um repositrio de
threads que permite ao desenvolvedor ao invs de criar as threads manualmente,
delegar ao pool a tarefa a ser executada que ele, por sua vez, se encarrega de criar ou
reutilizar alguma thread para executar a tarefa desejada. O grande benefcio de utilizar o
pool que o runtime do .NET dimensiona a quantidade de threads no pool de acordo
com o workload que realizado. Isso garantir que ao delegar uma tarefa para o pool,
muito provavelmente ele utilizar uma thread que ele j criou e, ao finalizar a tarefa, a
thread no ser descartada, apenas reciclada e devolvida ao pool para uso posterior.
H dentro do .NET Framework uma classe esttica chamada ThreadPool, que tem a
responsabilidade de gerenciar o pool de threads. Todas as threads que o pool
armazena internamente so do tipo background (a propriedade IsBackground est
definida como True), o que significa que se a aplicao (processo) finalizar, no
aguardar que as tarefas que esto sendo executadas finalizem.
Treinar Cursos e Treinamentos
31
C# 2008 - Mdulo II
32
using System;
using System.Threading;
namespace ExThreadPool
{
class Program
{
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(IniciaProcesso));
ThreadPool.QueueUserWorkItem(
new WaitCallback(IniciaProcesso), "Teste");
Console.WriteLine("Iniciando");
Console.WriteLine("Aguardando");
Console.ReadLine();
}
public static void IniciaProcesso()
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(500);
Console.WriteLine("Thread 1 " +
32
C# 2008 - Mdulo II
33
DateTime.Now.ToString("HH:mm:ss"));
}
}
public static void IniciaProcesso(object value_)
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(1000);
Console.WriteLine("Thread 2 " + value_ +
DateTime.Now.ToString("HH:mm:ss"));
}
}
}
}
As threads criadas manualmente bem como as threads que so geridas pela classe
ThreadPool, so executadas em paralelo aplicao. Isso quer dizer que ao chamar o
mtodo Start de uma Thread ou o mtodo QueueUserWorkItem da classe ThreadPool,
o controle da execuo voltar para a aplicao, no aguardando o processamento
desta thread.
33
C# 2008 - Mdulo II
34
Se InvokeRequired retorna true, chame Invoke com um delegate que faz a chamada
real para o Controle.
34
C# 2008 - Mdulo II
35
}
}
BackgroundWorker
Com o formulrio ativo no Windows Forms Designer, arraste dois controles de Button da
Toolbox para o formulrio .
No seu formulrio, importe os namespaces Sistema.ComponentModel e Sistema.Threading.
using
using
using
using
using
System;
System.ComponentModel;
System.Drawing;
System.Threading;
System.Windows.Forms;
35
C# 2008 - Mdulo II
36
RunWorkerCompleted.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// No referencie o BackgroundWorker diretamente.
BackgroundWorker bw = sender as BackgroundWorker;
// Extraia o arqumento
int arg = (int)e.Argument;
// Inicia a operao
e.Result = TimeConsumingOperation(bw, arg);
// se a Operao foi cancelada
if (bw.CancellationPending)
{
e.Cancel = true;
}
}
36
C# 2008 - Mdulo II
37
{
throw new Exception("Ocorreu erro.");
break;
}
// Pausa por um tempo determinado no sleepPeriod.
case 1:
{
Thread.Sleep(sleepPeriod);
break;
}
// Finaliza com sucesso.
case 2:
{
result = 23;
exit = true;
break;
}
default:
{
break;
}
}
if( exit )
{
break;
}
}
return result;
}
37
C# 2008 - Mdulo II
38
EXEMPLO DE XML
<Usuarios>
<Usuario>
<id>10</id>
<nome>Frederico Almeida</nome>
<idade>34</idade>
<cargo>Analista de sistemas</cargo>
</Usuario>
</Usuarios>
Inserir Registro:
Depois de criado precisamos muitas vezes inserir as informaes no arquivo xml j
existente, com isso precisamos inserir novos elementos utilizando o Mtodo
AppendChild.
XmlDocument doc = new XmlDocument();
string caminho = @"C:\Artigo_XML.xml";
doc.Load(caminho);
XmlNode linha = doc.CreateElement("Usuario");
38
C# 2008 - Mdulo II
XmlNode
XmlNode
XmlNode
XmlNode
39
Id = doc.CreateElement("id");
Nome = doc.CreateElement("nome");
Idade = doc.CreateElement("idade");
Cargo = doc.CreateElement("cargo");
Id.InnerText = "11";
Nome.InnerText = "Joo Pedro";
Idade.InnerText = "35";
Cargo.InnerText = "Financeiro";
linha.AppendChild(Id);
linha.AppendChild(Nome);
linha.AppendChild(Idade);
linha.AppendChild(Cargo);
doc.SelectSingleNode("/Usuarios").AppendChild(linha);
doc.Save(caminho);
Alterar Registro:
Para a alterao de um elemento do xml podemos utilizar:
XmlDocument doc = new XmlDocument();
string caminho = @"C:\Artigo_XML.xml";
doc.Load(caminho);
XmlNode no;
no = doc.SelectSingleNode(String.Format("/Usuarios/Usuario[id={0}]", 11));
no.SelectSingleNode("./cargo").InnerText = "Gerente Administrativo";
doc.Save(caminho);
Deletar Registro:
Para Deletar um elemento do xml baseado em uma condio podemos utilizar:
XmlDocument doc = new XmlDocument();
string caminho = @"C:\Artigo_XML.xml";
doc.Load(caminho);
foreach (XmlNode no in doc.DocumentElement.ChildNodes)
{
if (int.Parse(no.ChildNodes.Item(0).InnerText) == 10)
{
doc.DocumentElement.RemoveChild(no);
doc.Save(caminho);
return;
}
}
O item(0) representa a primeira coluna da tabela funcionrio que est representado pelo
n "id".
Treinar Cursos e Treinamentos
39
C# 2008 - Mdulo II
40
Reflection
Reflection (ou Reflexo) a habilidade que temos em descobrir e extrair informaes de
metadados de um determinado Assembly. Os metadados descrevem os campos
(propriedades, membros e eventos) de um tipo juntamente com seus mtodos e,
durante a compilao, o compilador gerar e armazenar metadados dentro do
Assembly. So os metadados que permitem uma das maiores faanhas dentro da
plataforma .NET, ou seja, escrevermos um componente em Visual C# e consum-lo em
uma aplicao em Visual Basic .NET. O Reflection no permite apenas extrair
informaes em runtime, mas tambm permitir que se carregue Assemblies, instancie
classes, invoque seus mtodos, etc.. Reflection algo muito poderoso que existe e
possibilita dar uma grande flexibilidade para a aplicao. O prprio .NET Framework
utiliza Reflection internamente em diversos cenrios, como por exemplo o Garbage
Collector examina os objetos que um determinado objeto referencia para saber se o
mesmo est ou no sendo utilizado. Alm disso, quando serializamos um objeto, o .NET
Framework utiliza Reflection para extrair todos os valores do membros internos do
objeto para persist-los. O prprio Visual Studio .NET utiliza informaes extradas via
Reflection para habilitar o Intellisense e mais, quando est desenvolvendo um formalrio
e vai at a janela de propriedades de um determinado controle, o Visual Studio .NET
extrai os membros do controle via Reflection para exibir e, conseqentemente, alterar
de acordo com a necessidade. Todas as classes que utilizaremos para Reflection esto
dentro do namespace System.Reflection
AppDomains
O cdigo gerenciado passa por um processo de verificao que deve ser executado
antes de rodar. Esse processo determina se o cdigo pode acessar endereo de
memria invlidos ou executar alguma outra ao que poderia causar alguma falha no
processo. O cdigo que passa por essa verificao chamado de type-safe e permite
ao CLR fornecer um grande nvel de isolamento, como um processo, s que com muito
mais performance. Um AppDomain criado para servir de container para uma aplicao
gerenciada. A inicializao de um AppDomain consiste em algumas tarefas, como por
exemplo, a criao da memria heap, onde todos os reference-types so alocados e de
onde o lixo coletado e a criao de um pool de threads, que pode ser utilizado por
qualquer um dos tipos gerenciados que esto carregados dentro do processo.
O Windows no fornece uma forma de rodar aplicao .NET. Isso feito a partir de uma
CLR Host, que uma aplicao responsvel por carregar o CLR dentro de um
processo, criando AppDomains dentro do mesmo e executando o cdigo das aplicaes
que desenvolvemos dentro destes AppDomains.
O .NET Framework disponibiliza uma classe chamada AppDomain que representa e
permite manipular AppDomains. Essa classe fornece vrios mtodos (alguns estticos)
que auxiliam desde a criao at o trmino de um AppDomain. Entre esses principais
mtodos, temos:
Mtodo
Descrio
40
C# 2008 - Mdulo II
41
CreateDomain
CurrentDomain
DoCallback
GetAssemblies
Unload
Assemblies
Nomenclatura dos Assemblies
A nomenclatura de um Assembly (conhecida como display name ou identidade do
Assembly) consiste em 4 informaes: nome (sem .exe ou .dll), verso, cultura e a
public key token (que ser nula se uma strong name no for definida). Para exemplificar
isso, vamos analisar o Assembly System.Data.dll da verso 2.0 do .NET Framework que
responsvel pelas classes de acesso a dados e tambm um Assembly customizado
chamado ExDLL, onde no foi criado uma strong name:
System.Data, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089
ExDLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
41
C# 2008 - Mdulo II
42
depois disso, poder extrair os tipos que ele expe. Para que isso seja possvel, o
namespace System.Reflection possui uma classe chamada Assembly que possui, alm
de seus mtodos de instncia, alguns mtodos estticos que so utilizados para
carregar um determinado Assembly. Entre esses mtodos estticos para carregamento
do Assembly temos:
Mtodo
Descrio
GetAssembly
GetCallingAssembly
GetEntryAssembly
GetExecutingAssembly
Load
LoadFile
LoadFrom
LoadWithPartialName
ReflectionOnlyLoad
using System;
using System.Reflection;
Assembly asb = Assembly.LoadFrom("C:\\Comp.dll");
Metadados
Os metadados so muito importantes dentro da plataforma .NET. Uma vez que um
Treinar Cursos e Treinamentos
42
C# 2008 - Mdulo II
43
System.Reflection.MemberInfo
MemberInfo uma classe abstrata que base para todas as classes utilizadas para
resgatar informaes sobre os membros sejam eles construtores, eventos, campos,
mtodos ou propriedades de uma determinada classe. Basicamente essa classe
fornece as funcionalidades bsicas para todas as classes que dela derivarem. Os
membros desta classe abstrata so:
Membro
Descrio
Name
MemberType
43
C# 2008 - Mdulo II
44
enumerador, temos:
All Especifica todos os tipos
Constructor Membro um construtor, representado pelo tipo
ConstructorInfo.
Custom O membro um membro customimzado.
Event O membro um evento, representado pelo tipo EventInfo.
Field O membro um campo, representado pelo tipo FieldInfo.
Method O membro um mtodo, representado pelo tipo MethodInfo.
NestedType O membro um tipo aninhado, representado pelo tipo
MemberInfo.
Property O membro uma propriedade, representada pelo tipo
PropertyInfo.
TypeInfo O membro um tipo, representado pelo tipo TypeInfo.
DeclaringType
ReflectedType
System.Type
Essa uma das mais importantes classes da plataforma .NET. Essa uma das
principais classes utilizadas para voc poder extrair informaes de um tipo.
System.Object possui um mtodo chamado GetType que retorna o tipo da instncia
corrente, sendo representado por um objeto do tipo Type. Sendo assim, todo e qualquer
objeto possui esse mtodo, j que todo tipo herda direta ou indiretamente dessa classe.
O mtodo GetType acima utilizamos quando j temos a instncia do objeto. Mas e
quando no a temos? Para esse caso, a classe Type fornece um mtodo esttico,
tambm chamado de GetType que, dado um tipo (atravs de uma string contendo o
AssemblyQualifiedName, que inclui o namespace at o nome do tipo que deve ser
carregado), ele retorna o objeto Type que o representa e, conseqentemente,
conseguir extrair as informaes de metadados do mesmo. Alm desse mtodo, a
classe Type ainda possui um mtodo interessante chamado GetArrayType, que retorna
um array de objetos do tipo Type, onde cada elemento representa o tipo correspondente
do elemento do array. Entre todos os membros da classe Type, podemos destacar:
Membro
Descrio
44
C# 2008 - Mdulo II
45
Assembly
BaseType
DeclaringType
IsAbstract
IsArray
IsByRef
IsClass
IsEnum
IsGenericParameter
IsGenericType
IsInterface
IsNested
IsValueType
FindInterfaces
FindMembers
GetConstructor
GetConstructors
45
C# 2008 - Mdulo II
46
GetEvent
GetEvents
GetField
GetFields
GetInterface
Dado uma string com o nome de uma Interface, ele retornar um objeto
do tipo Type que represente a mesma, desde que ela esteja
implementada no tipo.
GetInterfaces
GetMember
GetMembers
GetMethod
GetMethods
GetNestedType
GetNestedTypes
GetProperties
46
C# 2008 - Mdulo II
47
Dado uma string com o nome de uma propriedade existente no tipo, esse
mtodo retorna um objeto do tipo PropertyInfo representando a
propriedade.
using System;
int id = 123;
Type forma1 = id.GetType();
Type forma2 = Type.GetType("System.Int32");
Console.WriteLine(forma1.FullName);
Console.WriteLine(forma2.FullName);
Cada um dos mtodos retornam objetos especficos para cada um dos membros que
existem dentro de um determinado objeto. A partir daqui, como j somos capazes de
extrair o tipo de um objeto, iremos analisar esses objetos especficos, responsveis por
representar os membros do tipo, onde poderemos extrair informaes de metadados
referentes a cada um deles.
Mas para que podemos entender o grande potencial do Reflection, vamos criar uma
classe customizada, que possua membros, propriedades, mtodos e eventos para que
possamos extrair as informaes de metadados da mesma. Isso no quer dizer que no
seja possvel extrair as mesmas informaes de uma classe de dentro do .NET
Framework.
Remova a Class1 criada automaticamente e crie uma nova classe chamada cCliente.cs
Treinar Cursos e Treinamentos
47
C# 2008 - Mdulo II
using System;
namespace ExDLL
{
public class cCliente
{
public int X;
private int _id;
private string _nome;
public event EventHandler AlterouDados;
public cCliente() { }
public cCliente(int id, string nome)
{
this._id = id;
this._nome = nome;
}
public int Id
{
get { return _id; }
set
{
_id = value;
if (AlterouDados != null)
AlterouDados(this, EventArgs.Empty);
}
}
public string Nome
{
get { return _nome; }
set
{
_nome = value;
if (AlterouDados != null)
AlterouDados(this, EventArgs.Empty);
}
}
public string ExibeDados()
{
string msg = string.Format("{0} - {1}", Id, Nome);
return msg;
}
}
}
48
48
C# 2008 - Mdulo II
49
Para adicionar uma referncia para a DLL, clique com o boto direito do mouse sobre o
projeto e escolha a opo Add Reference.
Na janela que se abre, escolha a aba Browse e procure pela sua DLL.
49
C# 2008 - Mdulo II
System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.Linq;
System.Text;
System.Windows.Forms;
System.Reflection;
namespace ExReflection
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
ExDLL.cCliente _cli = new ExDLL.cCliente();
private void Form1_Load(object sender, EventArgs e)
{
_cli = new ExDLL.cCliente();
_cli.Id = 1;
_cli.Nome = "Frederico";
}
}
}
50
50
C# 2008 - Mdulo II
51
System.Reflection.FieldInfo
Essa classe representa um atributo pblico de um determinado tipo, fornecendo
informaes de metadata e atributos que possam estar aplicados ao membro. Essa
classe no possui um construtor pblico e, instncias da mesma, so retornadas a partir
dos mtodos GetField e GetFields da classe Type. No boto btnFieldInfo, escreva o
seguinte cdigo:
private void btnFieldInfo_Click(object sender, EventArgs e)
{
textBox1.Text = "";
foreach (FieldInfo fi in _tipo.GetFields())
{
textBox1.Text += string.Format("Nome: {0} - Tipo: {1}\r\n",
fi.Name, fi.FieldType);
}
}
System.Reflection.MethodBase
A classe MethodBase uma classe abstrata que fornece informaes a respeito de
mtodos e construtores de um determinado tipo, atributos que so aplicados aos
mesmos e mtodos e propriedades para manipulao de mtodos genricos. Ela
fornece tambm um mtodo chamado GetParameters, que retorna uma coleo de
objetos do tipo ParameterInfo, onde cada um deles representa um parmetro que pode
existir no mtodo.
A classe ParameterInfo possui uma propriedade chamada ParameterType que retorna
um objeto do tipo Type representando o tipo do parmetro e, alm dela, a classe
ParameterInfo possui algumas outras propriedades teis para extrairmos informaes
relacionadas a cada parmetro e, entre elas, temos a propriedade IsOut, que retorna um
valor booleano indicando se o parmetro trata-se de um parmetro de output.
A classe MethodBase ainda possui o mtodo GetMethodBody. Esse mtodo retorna um
objeto do tipo MethodBody, contendo o MSIL stream, variveis locais (declaradas dentro
do mtodo) e estruturas de excees.
A classe MethodBase classe serve como base para as classes concretas
ConstructorInfo e MethodInfo, que trazem informaes customizadas para cada um dos
tipos.
O primeiro deles, ConstructorInfo, trata-se de uma classe que representa um
determinado construtor pblico de um tipo, fornecendo informaes de metadados
respeito do construtor e tambm descobrindo os atributos que o construtor pode ter.
Essa classe no possui um construtor pblico e, instncias da mesma, so retornadas a
partir dos mtodos GetConstructor e GetConstructos da classe Type.
No boto btnMethodInfo, escreva o seguinte cdigo:
Treinar Cursos e Treinamentos
51
C# 2008 - Mdulo II
52
Como podemos ver, temos um lao For aninhado que utilizado para recuperar os
parmetros de um determinado construtor a partir de uma instncia de um objeto
ConstructorInfo.
A segunda e ltima classe que deriva de MethodBase, a classe MethodInfo, tem um
comportamento muito parecido com a classe ConstructorInfo, s que neste caso, cada
objeto deste representa um mtodo pblico de um tipo. A classe MethodInfo tambm
pode receber parmetros e ter atributos. A nica exceo que a classe MethodInfo
pode ter um tipo de retorno, ou seja, uma funo que retorna um valor qualquer e, para
isso, a classe MethodInfo fornece uma propriedade chamado ReturnType que retorna
um objeto do tipo Type representando o tipo que o mtodo retorna. Essa classe no
possui um construtor pblico e, instncias da mesma, so retornadas a partir dos
mtodos GetMethod e GetMethods da classe Type.
System.Reflection.PropertyInfo
Essa classe representa uma propriedade pblica de um determinado tipo, fornecendo
informaes de metadados e atributos que possam estar aplicados propriedade. Essa
classe no possui um construtor pblico e, instncias da mesma, so retornadas a partir
dos mtodos GetProperty e GetProperties da classe Type. A classe PropertyInfo possui
uma propriedade chamada PropertyType, que retorna um objeto do tipo Type
representando o tipo da propriedade e ainda, possui duas propriedades chamadas
CanRead e CanWrite, que retornam um valor booleano indicando se a propriedade
Treinar Cursos e Treinamentos
52
C# 2008 - Mdulo II
53
System.Reflection.EventInfo
Essa classe representa um evento pblico de um determinado tipo, fornecendo
informaes de metadata e atributos que possam estar aplicados ao evento. Essa
classe no possui um construtor pblico e, instncias da mesma, so retornadas a partir
dos mtodos GetEvent e GetEvents da classe Type. A classe EventInfo possui uma
propriedade chamada EventHandlerType, que retorna um objeto do tipo Type
representando o tipo do delegate utilizado para declarar o evento. No boto
btnEventInfo, escreva o seguinte cdigo:
private void btnEventInfo_Click(object sender, EventArgs e)
{
textBox1.Text = "";
foreach (EventInfo ei in _tipo.GetEvents())
{
textBox1.Text +=
string.Format("Evento: {0} - Tipo: {1}\r\n",
ei.Name, ei.EventHandlerType);
}
}
53
C# 2008 - Mdulo II
54
runtime. O Late Binding menos performtico que o Early Binding, mas te dar uma
maior flexibilidade, flexibilidade qual necessria quando trabalhamos com Reflection
para criar e instanciar os membros de um determinado tipo. justamente esse tipo de
binding que vamos utilizar aqui.
Antes de executar qualquer mtodo ou propriedade, temos primeiramente que instanciar
a classe em runtime e, para isso, existem duas formas. A primeira delas utilizando o
mtodo de instncia chamado CreateInstance da classe Assembly ou o mtodo
esttico, tambm chamado CreateInstance, da classe Activator. A diferena entre eles
que, no caso da classe Assembly, o tipo informado ser procurado dentro do Assembly
que a instncia da classe Assembly est referenciado; j no caso da classe Activator,
recebe o nome (identidade) de um Assembly de qual ela efetivamente dever criar a
instncia da classe. Internamente, o mtodo CreateInstance da classe Assembly, invoca
o mtodo CreateInstance da classe Activator. Ambos os mtodos retornam um objeto
do tipo System.Object com a instncia da classe especifica criada.
Ainda utilizando o exemplo da classe Cliente que construmos acima, vamos analisar
como devemos procede para criar a instncia da mesma em runtime. A classe Cliente
est agora em um outro Assembly (uma DLL) em local fsico diferente. Para fins de
exemplo, a instncia ser criada a partir do mtodo CreateInstance da instncia da
classe Assembly, qual foi criada com o retorno do mtodo esttico LoadFrom, tambm
da classe Assembly, qual analisamos anteriormente. O cdigo abaixo exemplifica como
instanciar a classe Cliente:
using System.Reflection;
Assembly asb = Assembly.LoadFrom(@"C:\ExDLL.dll");
object cliente = asb.CreateInstance("ExDLL.Cliente",
false, BindingFlags.CreateInstance, null, null, null, null);
Descrio
typeName
ignoreCase
bindingAttr
54
C# 2008 - Mdulo II
55
args
culture
activationAttributes
55
C# 2008 - Mdulo II
56
Essa classe tem um mtodo denominado ExibeDados, que retorna uma string com o Id
e o Nome do cliente concatenados. Como definimos no construtor da classe os valores
123 e Jos Torres, ao invocar o mtodo ExibeDados, esses valores devero ser
exibidos. Para que seja possvel invocar o mtodo em runtime, necessitamos utilizar o
mtodo InvokeMember da classe Type, que retorna um System.Object com o valor
retornado pelo mtodo. O exemplo abaixo ilustra como utiliz-lo:
Console.WriteLine(tipo.InvokeMember("ExibeDados",
BindingFlags.InvokeMethod, null, cliente, null));
Entre os parmetros que esse mtodo utiliza, temos (na ordem em que aparecem no
cdigo acima): uma string contendo o nome do construtor, mtodo, propriedade ou
campo a ser invocado (se informar uma string vazia, o membro padro ser invocado);
uma combinao das opes fornecidas pelo enumerador BindingFlags (detalhado mais
acima) indicando como a busca pelo membro ser efetuada; binder a ser utilizado para
a pesquisa do membro; a instncia do objeto de onde o mtodo ser pesquisado e
executado e, finalmente, um array de elementos do tipo System.Object, contendo os
parmetros necessrios para ser passado para o mtodo a ser executado.
Alm do mtodo, ainda h a possibilidade de invocarmos propriedades em runtime.
Podemos alm de ler as informaes de cada uma delas, podemos definir os valores a
elas. Para isso, utilizamos o mtodo GetProperty da classe Type, que retorna uma
instncia da classe PropertyInfo, que representa a propriedade e, atravs dela,
definimos os valores e extraimos para escrev-los, assim como mostrado no trecho de
cdigo abaixo:
PropertyInfo nome = tipo.GetProperty("Nome");
PropertyInfo id = tipo.GetProperty("Id");
nome.SetValue(cliente, "Mario Oliveira", null);
id.SetValue(cliente, 456, null);
56
C# 2008 - Mdulo II
57
Console.WriteLine(nome.GetValue(cliente, null));
Console.WriteLine(id.GetValue(cliente, null));
Descrio
ModuleBuilder
EnumBuilder
Representa um enumerador.
TypeBuilder
ConstructorBuilder
EventBuilder
57
C# 2008 - Mdulo II
58
FieldBuilder
Define um campo.
PropertyBuilder
MethodBuilder
ParameterBuilder
Define um parmetro.
ILGenerator
58
C# 2008 - Mdulo II
59
Globalization
As funcionalidades de globalizao esto no namespace System.Globalization.
Quando estamos falando de aplicaes para mltiplos idiomas e pases, temos que
entender dois aspectos muito importantes que so a globalizao e localizao:
Globalizao: O processo de globalizao a habilidade de construir
aplicaes/websites que so suportadas e adaptveis para as mais diferentes
culturas.
Localizao: a habilidade de localizar a aplicao para uma cultura e regio
especfica, criando tradues para os recursos que a aplicao utiliza em seu
interior. Um exemplo tpico a localizao de uma aplicao/website para o
portugus para vrias regies, como o Brasil (pt-BR) e Portugal (pt-PT).
As culturas so identificadas por um padro universal, contendo duas partes, sendo a
primeira delas dois caracteres minsculos que identificam o idioma. J na segunda
parte, existem mais dois caracteres maisculos que representam o pas.
Temos dois conceitos importantes que devemos levar em considerao.
Cultura corrente: utilizada para operarmos com formatao de datas e nmeros
e, alm disso, utilizada durante a escrita do cdigo
Cultura de interface (uiculture): utilizada pelo Resource Manager para analisar
uma cultura especfica e recuperar os recursos em tempo de execuo.
Para definirmos cada uma dessas culturas, utilizamos as propriedades CurrentCulture e
CurrentUICulture, respectivamente. Essas propriedades so estticas e esto contidas
dentro da classe Thread que, por sua vez, est dentro do namespace
System.Threading.
Utilizando Culturas
Cada instncia da classe CultureInfo representa uma cultura especfica, contendo
informaes especficas da cultura que ela representa e, entre essas informaes,
temos o nome da cultura, sistema de escrita, calendrios, como formatar datas, etc.
Membro
Descrio
Calendar
ComparerInfo
CultureTypes
59
C# 2008 - Mdulo II
60
CurrentUICulture
DateTimeFormat
DisplayName
EnglishName
InstalledUICulture
IsNeutralCulture
IsReadOnly
Name
60
C# 2008 - Mdulo II
61
NumberFormat
Parent
TextInfo
UseUserOverride
CreateSpecificCulture
GetCultureInfo
GetCultures
GetFormat
61
C# 2008 - Mdulo II
62
}
static void Show(CultureInfo[] cultures)
{
Console.WriteLine(Thread.CurrentThread.CurrentCulture.Name);
foreach (CultureInfo ci in cultures)
{
Console.WriteLine("------------------------");
Console.WriteLine(
ci.DisplayName);
Console.WriteLine(
ci.DateTimeFormat.DateSeparator);
Console.WriteLine(
ci.DateTimeFormat.FirstDayOfWeek.ToString());
Console.WriteLine(
ci.NumberFormat.CurrencyDecimalSeparator);
Console.WriteLine(
new DateTime(2009, 07, 26).ToString(
ci.DateTimeFormat));
Console.WriteLine(
double.Parse("9,52").ToString(ci.NumberFormat));
}
}
}
}
DateTimeFormatInfo
A classe DateTimeFormatInfo ir auxiliar na formatao de data e hora de acordo com a
cultura selecionada. Todas as propriedades que essa classe possui j refletem as
informaes da cultura especfica quando voc extrai a instncia dessa classe a partir
do mtodo GetFormat ou da propriedade DateTimeFormat da classe CultureInfo.
Especificador
Descrio
62
C# 2008 - Mdulo II
T
63
A estrutura DateTime fornece alguns mtodos que serve como wrapper para as
propriedades que citamos acima e, alm disso, o mtodo ToString desta estrutura
possui alguns overloads que permitem customizarmos a formatao. Para testarmos as
formataes acima, vamos utiliz-la no exemplo a seguir:
DateTime hoje = DateTime.Now;
Console.WriteLine(hoje.ToString("d"));
Console.WriteLine(hoje.ToString("D"));
Console.WriteLine(hoje.ToString("f"));
Console.WriteLine(hoje.ToString("F"));
Console.WriteLine(hoje.ToString("t"));
Console.WriteLine(hoje.ToString("T"));
Console.WriteLine(hoje.ToString("dd/MM/yyyy"));
NumberFormatInfo
Essa classe tambm fornece alguns caracteres, com padres pr-determinados que
podemos utilizar para customizar a formatao de um determinado valor. Alm disso,
ela fornece tambm propriedades que podemos definir os smbolos, separadores
decimais, etc. Atravs da tabela abaixo, vamos analisar os caracteres que temos
disponveis para a formatao de valores numricos:
Caracter
Descrio
c, C
Formato monetrio.
d, D
Formato decimal.
e, E
f, F
Formato fixo.
g, G
Formato padro.
n, N
Formato numrico.
r, R
x, X
Formato hexadecimal.
63
C# 2008 - Mdulo II
64
Mais uma vez, importante dizer que quando utilizamos as formataes dessa forma,
apesar de explicitamente no estarmos utilizando a classe NumberFormatInfo, ela
extrada automaticamente da thread corrente e, conseqentemente, formatando os
valores baseando-se nessas informaes.
Propriedade
Descrio
CurrencyDecimalDigits
CurrencyGroupSizes
CurrentInfo
NegativeSign
NumberDecimalDigits
NumberDecimalSeparator
NumberGroupSeparator
NumberGroupSizes
PositiveSign
64
C# 2008 - Mdulo II
65
Encoding
Existem vrios padres de codificao disponveis para representar os caracteres nos
mais diversos idiomas. Inicialmente o padro ASCII, que baseado no alfabeto ingls
foi desenvolvido pela IBM. Esse padro utiliza 7 bits mas como h idiomas que
possuem vrios outros caracteres, esse padro no suporta todos os idiomas. Neste
momento introduzido o padro Unicode, que possibilita 8 bits para os caracteres. Alm
de suportar os caracteres definidos pelo ASCII, ele tambm suporta todos os caracteres
usados nos mais diversos idiomas. Atualmente, temos 3 verses do padro Unicode:
UTF-8, UTF-16 e UTF-32. O que diferem nestes padres, a quantidade de bytes
utilizados para armazenar os caracteres: o primeiro utiliza 1 byte, o segundo 2 bytes e o
ltimo 4 bytes.
O .NET Framework suporta esses padres que podemos, atravs de classes, utiliz-los
em nossas aplicaes. As classes para isso esto contidas dentro do namespace
System.Text e, uma das princpais delas a classe Encoding.
Classe
Descrio
ASCIIEncoding
UTF7Encoding
UTF8Encoding
UnicodeEncoding
UTF32Encoding
65
C# 2008 - Mdulo II
66
Alm das propriedades estticas que vimos acima que a classe Encoding fornece, ainda
existem algumas outras propriedades e mtodos importantes.
Membro
Descrio
BodyName
CodePage
Default
EncodingName
Convert
GetBytes
GetDecoder
GetEncoder
GetPreamble
GetString
66
C# 2008 - Mdulo II
{
static void Main(string[] args)
{
string msg = "Codificao - .NET Framework";
ASCIIEncoding ascii = new ASCIIEncoding();
UnicodeEncoding unicode = new UnicodeEncoding();
byte[] asciiBytes = ascii.GetBytes(msg);
byte[] unicodeBytes = unicode.GetBytes(msg);
ShowBytes(asciiBytes);
ShowBytes(unicodeBytes);
string asciiMsg = ascii.GetString(asciiBytes);
string unicodeMsg = unicode.GetString(unicodeBytes);
Console.WriteLine(Environment.NewLine);
Console.WriteLine(asciiMsg);
Console.WriteLine(unicodeMsg);
Console.ReadLine();
}
static void ShowBytes(byte[] msg)
{
Console.WriteLine(Environment.NewLine);
foreach (byte b in msg)
{
Console.Write("[{0}]", b);
}
}
}
}
67
67
C# 2008 - Mdulo II
68
UserControl
Para criarmos um user control, devemos criar uma classe que herde de
System.Windows.Forms. UserControl. Crie um novo projeto Windows Forms e adicione
um novo controle do usurio (UserControl)
Se seu controle no estiver em modo de desenho (Design Mode), alterne para este
modo; voc deve estar vendo algo como a figura abaixo:
68
C# 2008 - Mdulo II
69
conforme a situao;
o Button permanea alinhado direita, mantendo
Para atingir esse objetivo, altere as propriedades indicadas abaixo:
TextBox: Anchor = Left, Rigth, Top
Button: Anchor = Rigth, Top
Escreva o cdigo abaixo no seu controle.
namespace ExUserControl
{
public partial class UserControl1 : UserControl
{
public delegate void SelecionouHandler(string arquivo_);
public event SelecionouHandler Selecionou;
public string Filter
{
get; set;
}
public string Label
{
get{return label1.Text;}
set { label1.Text = value; }
}
public override string Text
{
get { return textBox1.Text; }
set { textBox1.Text = value; }
}
public string InitialDir
{
get; set;
}
public bool CanType
{
get { return textBox1.ReadOnly; }
set { textBox1.ReadOnly = value; }
}
public UserControl1()
{
InitializeComponent();
Filter = "Todos os arquivos (*.*)|*.*";
Label = "Selecione o arquivo:";
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openDlg = new OpenFileDialog();
openDlg.Title = Text;
openDlg.Filter = Filter;
openDlg.FilterIndex = 0;
openDlg.InitialDirectory = InitialDir;
if (openDlg.ShowDialog() == DialogResult.OK)
{
69
seu
tamanho.
C# 2008 - Mdulo II
70
textBox1.Text = openDlg.FileName;
if (Selecionou != null)
Selecionou(textBox1.Text);
}
}
}
}
Visualize as propriedades do controle, e veja que nossas propriedades (Filter, InitialDir &
CanType) j esto l.
Agora vamos codificar o evento Selecionou. Procure o evento na lista de eventos:
70
C# 2008 - Mdulo II
71
WCF
O WCF unificou as vrias tecnologias de programao distribudas na plataforma
Microsoft em um nico modelo, baseando-se na arquitetura orientada servios (SOA).
Essa nova API facilita consideravelmente o aprendizado e desenvolvimento, j que o
WCF est totalmente desacoplado das regras de negcios que sero expostas pelo
servio.
Estrutura
A estrutura de um servio WCF no muito complexa, pois devemos utilizar conceitos
puros de programao .NET para a criao do contrato e da classe que representar o
servio. Alm disso, o WCF tambm suporta a utilizao de tipos complexos, como
classes que criamos para atender uma determinada necessidade.
O primeiro passo na criao do servio a definio do contrato. o contrato que
determinar quais operaes estaro expostas, quais informaes essas operaes
necessitam para ser executadas e tambm qual ser o tipo de retorno. O contrato nada
mais que uma Interface que, por sua vez, dever possuir os mtodos (apenas a sua
assinatura) que sero expostos. A Interface que servir como contrato dever ser
obrigatoriamente decorada com o atributo ServiceContractAttribute pois, caso contrrio,
uma exceo do tipo InvalidOperationException ser disparada antes da abertura do
host.
Nem sempre todos os membros expostos pela Interface devem ser expostos para o
servio e, justamente por isso, todas as operaes que sero disponibilizadas devem
ser decoradas com o atributo OperationContractAttribute. Vale lembrar que o WCF
obriga a termos no mnimo uma operao definida com este atributo, j que no faz
sentido publicar um servio que no tenha nenhuma operao a ser executada. Caso a
Interface no possua nenhuma operao definida com este atributo, uma exceo do
tipo InvalidOperationException tambm ser disparada antes da abertura do host.
using System;
using System.ServiceModel;
[ServiceContract]
public interface IContrato
{
[OperationContract]
Usuario RecuperarUsuario(string nome);
}
71
C# 2008 - Mdulo II
72
A partir do Service Pack 1 do .NET Framework 3.5 esse comportamento foi mudado.
Visando o suporte ao POCO (Plain Old C# Objects), a Microsoft tornou mais flexvel a
utilizao de data contracts em servios WCF, no obrigando s classes, propriedades
e campos serem decorados com os atributos acima citados. Com isso, apenas
propriedades do tipo escrita/leitura sero serializadas. A partir do momento que voc
decora a classe com o atributo DataContractAttribute, voc tambm dever especificar,
via DataMemberAttribute, quais campos devero ser serializados.
Uma vez que o contrato do servio esteja definido e os possveis tipos que ele expe
tambm estejam devidamente configurados, o prximo passo a criao da classe que
representa o servio. Esta classe dever implementar todos os membros expostos pela
Interface que define o contrato do servio, inclusive aqueles que no esto marcados
com o atributo OperationContractAttribute, lembrando que a implementao de uma
Interface em uma classe uma imposio da linguagem, e no do WCF.
A implementao dos mtodos poder conter a prpria regra de negcio, bem como
pode servir de wrapper para algum outro componente ou servio. Alm disso, as
classes que representam o servio tambm podem configurar alguns outros recursos
fornecidos pelo WCF e que esto acessveis atravs de behaviors, como por exemplo:
transaes, sesses, segurana, etc.
using System;
public class Servico : IContrato
{
public Usuario RecuperarUsuario(string nome)
{
return new Usuario() { Nome = nome };
}
}
Por si s esta classe no trabalha, pois dever ser consumida pelo WCF. Mas afinal,
como se determina que esta classe responsvel por atender as requisies? Isso
realizado atravs do host, ou melhor, da classe ServiceHost. Logo no construtor desta
classe, voc dever passar uma instncia da classe Type, apontando para a classe que
Treinar Cursos e Treinamentos
72
C# 2008 - Mdulo II
73
Hosting
Uma das grandiosidades do WCF a possibilidade de utilizar qualquer tipo de aplicao
como host, ou seja, ele no tem uma dependncia de algum software, como o IIS
(Internet Information Services), como acontecia com os ASP.NET Web Services. O
WCF pode expor servios para serem acessados atravs dos mais diversos tipos de
protocolos,
como
por
exemplo:
HTTP,
TCP,
IPC
e
MSMQ.
O host representado dentro do WCF pela classe ServiceHost ou uma de suas
variaes e, atravs dela que efetuamos vrias configuraes, como endpoints,
segurana, etc. Em seu construtor, ela espera a classe que representa o servio,
podendo ser definida atravs de seu tipo (classe Type) ou atravs de uma instncia
desta mesma classe anteriormente criada (Singleton). Para o exemplo utilizado neste
artigo, a configurao parcial do host fica da seguinte forma:
using System;
using System.ServiceModel;
using (ServiceHost host = new ServiceHost(typeof(Servico),
new Uri[] { new Uri("net.tcp://localhost:9393") }))
{
//endpoints
host.Open();
Console.ReadLine();
}
Endpoints
Os endpoints so uma das caractersticas mais importantes de um servio, pois por
onde toda a comunicao realizada, pois fornece o acesso aos clientes do servio
WCF que est sendo disponibilizado. Para compor um endpoint, basicamente
precisamos definir trs propriedades que obrigatoriamente precisamos para poder
trabalhar: address (A), binding (B) e contract (C) e, opcionalmente, definir alguns
behaviors. A figura abaixo ilustra a estrutura dos endpoints e onde eles esto situados:
73
C# 2008 - Mdulo II
74
O address consiste em definir um endereo nico que permitir aos clientes saber onde
o servio est publicado. O endereo geralmente definido atravs de uma instncia da
classe Uri. Essa classe fornece um construtor que recebe uma string, contendo o
protocolo, o servidor, a porta e o endereo do servio (usado para diferenciar entre
muitos servios no mesmo local), tendo a seguinte forma: scheme://host[:port]/[path].
Cada uma dessas configuraes so representadas respectivamente pelas seguintes
propriedades da classe Uri: Scheme, Host, Port e AbsolutePath.
O protocolo indica sob qual dos protocolos suportados pelo WCF o servio ser
exposto. Atualmente temos os seguintes protocolos: HTTP (http://), TCP (net.tcp://), IPC
(net.pipe://) e MSMQ (net.msmq://). O host refere-se mquina onde o servio ir ser
executado, podendo inclusive referenciar o localhost. A porta permite especificarmos
uma porta diferente do valor padro e, quando omitida, ela sempre assumir a porta
padro especificada pelo protocolo. E, finalmente, temos o path, que utilizado quando
desejamos diferenciar entre vrios servios expostos sob um mesmo protocolo, host e
porta.
O binding indica como a comunicao ser realizada com aquele endpoint, como por
exemplo, qual transporte ser utilizado (HTTP, TCP, etc), qual a codificao utilizada
(Binary ou Text) para serializar a mensagem, segurana, suporte transaes, etc.
Finalmente, a ltima caracterstica de um endpoint o contrato. Como j vimos acima, o
contrato representado por uma Interface e, uma vez que ele definido como um
contrato de servio, so esses membros que sero disponibilizados aos clientes em
forma de operaes, definindo os parmetros de entrada e o tipo de retorno e o formato
da mensagem (request-reply, one-way ou duplex).
Configurao do Cliente
Para que possamos fazer o uso do servio em aplicaes cliente, necessrio efetuar a
referncia deste servio. A referncia consiste em criar uma classe que encapsular
todo o acesso para o servio, que tambm conhecida como proxy. Este processo ir
ler os metadados do servio, criando o proxy com os mesmos membros expostos,
dando a impresso ao consumidor que est chamando uma classe local mas, em tempo
de execuo, a requisio ser encaminhada para o servio remoto.
Podemos efetuar a criao do proxy de trs formas diferentes. A primeira delas
atravs da referncia do servio por meio da IDE do Visual Studio .NET que, por sua
vez, fornece uma opo chamada Add Service Reference que exige a referncia para o
servio. A segunda opo fazer uso do utilitrio svcutil.exe que, dada uma URL at o
Treinar Cursos e Treinamentos
74
C# 2008 - Mdulo II
75
servio, ele tambm capaz de gerar a classe que representar o proxy. Ambas as
opes tambm automatizam a criao do arquivo de configurao, que fornece de
forma declarativa todas as configuraes do servio.
Ao efetuar a referncia, ser criada uma representao local do contrato (Interface),
bem como os tipos complexos que fazem parte do servio. Alm disso, a classe que
representa o proxy herda diretamente da classe abstrata e genrica
ClientBase<TChannel> que fornece toda a implementao necessria para permitir aos
clientes se comunicarem com o respectivo servio. Essa classe ir configurar em tempo
de execuo as propriedades necessrias para efetuar a requisio, extraindo tais
informaes do arquivo de configurao. a partir desta classe que comeamos a criar
o cdigo cliente para efetuar a requisio:
using System;
using Client.Servico;
using (ContratoClient proxy = new ContratoClient())
{
Usuario usuario = proxy.RecuperarUsuario("Israel Aece");
Console.WriteLine(usuario.Nome);
}
A terceira e ltima forma que existe para efetuar a comunicao entre o cliente e o
servio realizar toda a configurao de forma manual. Isso obriga a conhecer
exatamente o binding e suas respectivas configuraes, qual o endereo onde o servio
est publicado e, principalmente, a Interface do contrato e os tipos que ela expe devem
estar compartilhados entre o cliente e o servio. Apesar deste compartilhamento ser
simples de realizar, pois basta isolar os tipos em um assembly (DLL), o problema
quando o nmero de clientes aumenta consideravelmente, dificultando a distrubuio.
De qualquer forma, abaixo consta um exemplo de como efetuar essa configurao:
using System;
using System.ServiceModel;
using (ChannelFactory<IContrato> srv =
new ChannelFactory<IContrato>(new NetTcpBinding(),
new EndpointAddress("net.tcp://localhost:9393/")))
{
Usuario u = srv.CreateChannel().RecuperarUsuario("Israel Aece");
Console.WriteLine(u.Nome);
}
75
C# 2008 - Mdulo II
O Wizard do Visual Studio cria o projeto com alguns arquivos para voc.
76
76
C# 2008 - Mdulo II
77
System;
System.Collections.Generic;
System.Linq;
System.Runtime.Serialization;
System.ServiceModel;
System.Text;
namespace CalcWS
{
// NOTE: If you change the interface name "ICalc" here, you must also
update the reference to "ICalc" in Web.config.
[ServiceContract]
public interface ICalc
{
[OperationContract]
double Somar(double val1_, double val2_);
[OperationContract]
double Subtrair(double val1_, double val2_);
[OperationContract]
double Multiplicar(double val1_, double val2_);
[OperationContract]
double Dividir(double val1_, double val2_);
}
}
77
C# 2008 - Mdulo II
78
System;
System.Collections.Generic;
System.Linq;
System.Runtime.Serialization;
System.ServiceModel;
System.Text;
namespace CalcWS
{
// NOTE: If you change the class name "Calc" here, you must also update
the reference to "Calc" in Web.config.
public class Calc : ICalc
{
#region ICalc Members
public double Somar(double val1_, double val2_)
{
return val1_ + val2_;
}
public double Subtrair(double val1_, double val2_)
{
return val1_ - val2_;
}
public double Multiplicar(double val1_, double val2_)
{
return val1_ * val2_;
}
public double Dividir(double val1_, double val2_)
{
return val1_ / val2_;
}
#endregion
}
}
Criando o cliente
Para criarmos o cliente, precisamos adicionar um novo projeto nossa soluo.
78
C# 2008 - Mdulo II
79
79
C# 2008 - Mdulo II
System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.Linq;
System.Text;
System.Windows.Forms;
namespace WSClient
{
public partial class Form1 : Form
{
public Form1()
{
80
80
C# 2008 - Mdulo II
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
CalcRef.CalcClient c = new WSClient.CalcRef.CalcClient();
textBox3.Text = c.Somar(
double.Parse(textBox1.Text),
double.Parse(textBox2.Text)).ToString();
}
private void button2_Click(object sender, EventArgs e)
{
CalcRef.CalcClient c = new WSClient.CalcRef.CalcClient();
textBox3.Text = c.Subtrair(
double.Parse(textBox1.Text),
double.Parse(textBox2.Text)).ToString();
}
private void button3_Click(object sender, EventArgs e)
{
CalcRef.CalcClient c = new WSClient.CalcRef.CalcClient();
textBox3.Text = c.Multiplicar(
double.Parse(textBox1.Text),
double.Parse(textBox2.Text)).ToString();
}
private void button4_Click(object sender, EventArgs e)
{
CalcRef.CalcClient c = new WSClient.CalcRef.CalcClient();
textBox3.Text = c.Dividir(
double.Parse(textBox1.Text),
double.Parse(textBox2.Text)).ToString();
}
}
}
81
81