Desenvolvedores.Net - TechBlog

Monthly Archives: fevereiro 2011

Usando dll C# como um ActiveX/DLL

4
1 Estrela2 Estrelas3 Estrelas4 Estrelas5 Estrelas (1 votos, média: 5,00 de 5)
Loading...
25 de fevereiro de 2011
Nem todas as linguagens suportam o acesso às classes, métodos e propriedades das DLL’s criadas em .NET de uma forma “automática”, “nativa”.
Muitas vezes temos a necessidade de disponibilizar estes acessos para linguagens que suportam o uso de ActiveX. (veja: http://pt.wikipedia.org/wiki/ActiveX)E isso é bem simples de se fazer em .NET. Vamos ver como.

Iremos criar um novo projeto do tipo Class Library no Visual Studio eu dei o nome de ActiveX (criativo não?).
Iremos criar uma classe chamada de “MinhaClasse” (minha criatividade para nomes está a mil hoje).
Primeiro vamos ver o código de MinhaClasse
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ActiveX
{
    //define o tipo de interface da classe

    [ClassInterface(ClassInterfaceType.AutoDual)]

    //registra um identificador para a classe no registry
    [ProgId("ActiveX.MinhaClasse")]

    //faz com que todos os métodos e propriedades da classe sejam visíveis
    [ComVisible(true)]

    public class MinhaClasse
    {
        private string mPropriedade;

        public string MinhaPropriedade
        {
            get { return mPropriedade; }
            set { mPropriedade = value; }
        }

        public string MeuMetodo()
        {
            return "MeuMetodo";
        }

        //este método eu não quero que seja visível. Então somente pra ele eu uso o comvisible = false
        [ComVisible(false)] //este método não ira aparecer no VB6 por ex.
        public string MeuMetodoOculto()
        {
            return "MeuMetodoOculto";
        }
    }
}
Ok! Feito isso podemos compilar nossa classe, que não irá dar erro, mas também não vai funcionar, temos que marcar um checkBox mágico para que a DLL como um todo seja declarada como ActiveX.
Para isso vá em “Project” -> “Properties” -> Aba “Build” e marque a opção “Register for COM Interop”.
Veja na animação:
Feito isso, compilaremos novamente a nossa DLL. Mas também não iria funcionar só de compilar. 🙂
Como todo bom ActiveX que se preze temos que registrar.
Utilize a seguinte sintaxe:
para registrar :
%windir%\Microsoft.NET\Framework\XXX\RegAsm.exe “Caminho Completo do ActiveX.dll” /tlb
Onde XXX é a versão do seu framework
Pronto, agora sim podemos usar a nossa DLL como um activeX, para isso vamos usar o VBScript para criarmos o objeto e um arquivo HTML com java script como exemplo.
VBScript
Dim activex
set activex = CreateObject("ActiveX.MinhaClasse")
MsgBox activex.MeuMetodo
Agora em HTML com java script

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>

    <script language="javascript" type="text/javascript">
    function Load()
    {
        var activeX;
        activeX = new ActiveXObject("ActiveX.MinhaClasse");
        alert (activeX.MeuMetodo());
    }
    </script>

    <title>Testando ActiveX em .NET</title>
</head>
<body onload="Load();">
</body>
</html>
Este artigo foi apenas uma parte do que se é possível fazer, mas não podemos esquecer dos eventos e interfaces que nossas dlls podem ter.
Mas isso vai ficar para uma próxima vez. 🙂
É isso ai pessoal 🙂
Até o próximo
♦ Marcelo

About Marcelo

Nascido em Juruaia/MG em uma fazenda de criação de búfalos, e residindo na região Sul do Brasil. Trabalha com desenvolvimento de aplicações desde os 17 anos. Atualmente é Arquiteto Organizacional na Unimake Software. Para saber mais ... http://desenvolvedores.net/marcelo []'s

Inno Setup – Alterando variáveis de ambiente

1
1 Estrela2 Estrelas3 Estrelas4 Estrelas5 Estrelas (1 votos, média: 5,00 de 5)
Loading...
23 de fevereiro de 2011
Recentemente, no fórum, foi postada uma dúvida no fórum em relação a alterar as variáveis de ambiente pelo Inno Setup.Aproveitei a deixa para fazer uma postagem sobre isso.Fórum: http://techblog.desenvolvedores.net/bbpress/topic.php?id=11.

O Inno Setup pode ser baixado em http://www.jrsoftware.org/isdl.php é um ótimo gerador de instalador para suas aplicações e não deixa nada a desejar eu o uso desde sua segunda versão para instalar as minhas aplicações.

Para o artigo vou pegar como exemplo a variável Path, que foi a dúvida postada, mas isto serve para qualquer tipo de variável.

Para as versões NT/2000/XP/2003 e atuais. As variáveis de ambiente ficam na seguinte chave do registro.

Para máquina:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment

Para o usuário:
HKEY_CURRENT_USER\Environment

Para as versões 95/98/Me, é necessário modificar o arquivo AUTOEXEC.BAT. Mas não vamos falar sobre isso aqui.

O caminho na chave do registro para Path é um valor do tipo REG_EXPAND_SZ.
Como a documentação do Inno Setup para o Registro afirma na seção, há uma maneira de acrescentar valores a esses elementos:


Em um valor do tipo expandsz, ou multisz, você pode usar uma constante especial chamada {OldData} no parâmetro ValueData. {OldData} será substituída com os dados anteriores do valor do registro. A constante {OldData} pode ser útil se você precisar acrescentar uma string para um valor já existente, por exemplo, {OldData}, {app}. Se o valor não existe ou o valor existente não é um tipo string, a constante {OldData} não será usada.

Original:

On a string, expandsz, or multisz type value, you may use a special constant called {olddata} in this parameter. {olddata} is replaced with the previous data of the registry value. The {olddata} constant can be useful if you need to append a string to an existing value, for example, {olddata};{app}. If the value does not exist or the existing value isn’t a string type, the {olddata} constant is silently removed.

Então, para acrescentar um caminho a uma seção do Registro podemos usar:

[Registry]
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};C:\foo";

Onde C:\foo é o nosso caminho
Mas deste modo, isso iria repetir o caminho quando você instalar uma segunda vez, o que deve ser corrigido também. No Inno podemos usar uma função em pascal que retorne se a variável Path realmente precisa ser alterada ou não, para isso iremos usar o parâmetro Check

Veja:

[Registry]
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};C:\foo"; Check: CheckKey('Path','C:\foo')

Vamos escrever a função CheckKey, esta função lê o valor do caminho original e verifica se o valor informado já está na chave do registro.

[Code]

//@param key: chave do registro a ser validada
//@param value: valor a ser procurado
function CheckKey(key:string; value: string): boolean;
var
OrigPath: string;
begin

if not RegQueryStringValue(HKEY_LOCAL_MACHINE,
'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
key, OrigPath)
then begin
//vai retornar true se o valor não existir
Result := True;
exit;
end;
// se existir, temos que procurar por ele na variável inteira
// A função Pos() retorna 0 se não encontrado
Result := Pos(';' + value + ';', ';' + OrigPath + ';') = 0;
end;

Código completo do script para estudo:

#define MyAppName "Desenvolvedores"
#define MyAppVersion "1.5"
#define MyAppPublisher "desenvolvedores.net"
#define MyAppURL "http://desenvolvedores.net"
#define MyAppExeName "desenvolvedores.exe"

[Setup]
AppId={{006DC1BE-0C38-46DF-AF73-CC79E3A1E9F4}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DisableDirPage=yes
DefaultGroupName={#MyAppName}
OutputBaseFilename=setup
Compression=lzma
SolidCompression=yes

[Languages]
Name: "portugues"; MessagesFile: "compiler:Languages\Portugues.isl"

[Registry]
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};C:\foo"; Check: CheckKey('Path','C:\foo')

[Code]

//@param key: chave do registro a ser validada
//@param value: valor a ser procurado
function CheckKey(key:string; value: string): boolean;
var
  OrigPath: string;
begin

  if not RegQueryStringValue(HKEY_LOCAL_MACHINE,
    'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
    key, OrigPath)
  then begin
  //vai retornar true se o valor não existir
    Result := True;
    exit;
  end;
  // se existir, temos que procurar por ele na variável inteira
  // A função Pos() retorna 0 se não encontrado
  Result := Pos(';' + value + ';', ';' + OrigPath + ';') = 0;
end;

Chegamos ao fim do artigo. Desde modo podemos modificar as variáveis de ambiente que precisamos.
Mas isso é apenas uma pequena parte do que podemos fazer com o Inno Setup e acesso ao registro.

Uma ótima fonte de ajuda também é o FAQ do Inno http://www.jrsoftware.org/isfaq.php

É isso ai pessoal 🙂
Até o próximo
♦ Marcelo

About Marcelo

Nascido em Juruaia/MG em uma fazenda de criação de búfalos, e residindo na região Sul do Brasil. Trabalha com desenvolvimento de aplicações desde os 17 anos. Atualmente é Arquiteto Organizacional na Unimake Software. Para saber mais ... http://desenvolvedores.net/marcelo []'s

Polimorfismo (POO)

10
1 Estrela2 Estrelas3 Estrelas4 Estrelas5 Estrelas (8 votos, média: 3,50 de 5)
Loading...
12 de fevereiro de 2011
Para um melhor entendimento deste Artigo veja o Índice (Programação Orientada a Objetos)
Iremos entrar agora em nosso último tópico sobre POO, e  muito interessante que é polimorfismo.Se você seguiu toda a trajetória do artigo sobre POO deve ter visto várias formas de polimorfismo (isso não foi um trocadilho) durante a leitura.

Vimos em:

Herança (POO)
Tipos Genéricos (Generics) (POO)
Abstração e Interface (POO)

Leia este artigo e depois do entendimento, volte a eles e tente identificar o uso do polimorfismo.

Aqui iremos abordar o polimorfismo de uma forma mais ampla e detalhada. Então vamos lá.

Polimorfismo

Etimologicamente, polimorfismo quer dizer:

1 Que se apresenta ou ocorre sob formas diversas.
2 Que assume ou passa por várias formas, fases etc.

Em orientação a objetos podemos dizer também que o objeto pode ter “vários comportamentos”.

Quando você chama um método ele pode se referir a qualquer objeto, por exemplo o método “Abrir()”, ele pode abrir uma tampa de garrafa, uma janela, uma porta, pode abrir alguma coisa.

Em polimorfismo é necessário que os métodos tenham a mesma assinatura, o mecanismo utilizado é o de redefinição de métodos (Overriding Definições – Intermediário (POO)) , não confundir com sobrecarga de métodos (Overload Definições – Intermediário (POO)).

Em polimorfismo podemos:

1 Instanciar objetos diferentes para um mesmo tipo.
2 Substituir condicionais com o polimorfismo.
3 Usar parâmetros que aceitam diferentes tipos de objetos desde que tenham a mesma herança de classes.

Vamos à alguns exemplos para reforçarmos as idéias.

Vamos criar nossas classes que servirão de base para todo o exemplo.

Iremos criar uma calculadora bem simples, que implemente as quatro operações básicas.

Classe Base

namespace Polimorfismo
{
    /// <summary>
    /// Classe base para efetuar os cálculos matemáticos
    /// </summary>
    abstract class CalculoMatematico
    {
        public virtual double Valor1 { get; set; }
        public virtual double Valor2 { get; set; }

        public abstract double Resultado();
    }
}

Multiplicação

namespace Polimorfismo
{
    class Multiplicacao : CalculoMatematico
    {
        public override double Resultado()
        {
            return Valor1 * Valor2;
        }
    }
}

Divisão

namespace Polimorfismo
{
    class Divisao : CalculoMatematico
    {
        public override double Resultado()
        {
            return Valor1 / Valor2;
        }
    }
}

Adição

namespace Polimorfismo
{
    class Adicao : CalculoMatematico
    {
        public override double Resultado()
        {
            return Valor1 + Valor2;
        }
    }
}

Subtração

namespace Polimorfismo
{
    class Subtracao : CalculoMatematico
    {
        public override double Resultado()
        {
            return Valor1 - Valor2;
        }
    }
}

Vamos agora ao primeiro exemplo.
Partindo de um mesmo tipo de objeto, podemos instanciar os outros tipos.
Mas para isso todos as classes devem implementar a mesma classe Pai.

namespace Polimorfismo
{
    class Program
    {
        static void Main(string[] args)
        {
            //veja que definimos o tipo
            //como CalculoMatematico
            CalculoMatematico calc;

            //aqui é criado como Adicao
            calc = new Adicao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(calc.Resultado().ToString("N2"));

            //aqui é criado como Divisao
            calc = new Divisao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(calc.Resultado().ToString("N2"));

            //aqui é criado como Subtracao
            calc = new Subtracao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(calc.Resultado().ToString("N2"));

            //aqui é criado como Multiplicacao
            calc = new Multiplicacao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(calc.Resultado().ToString("N2"));

            Console.ReadKey();
        }
    }
}

O nosso segundo item diz que podemos substituir condicionais com o uso de polimorfismo.
Será?
Vamos ver os exemplos abaixo, reparem bem na diferença entre os dois métodos da classe Calculadora

Definição da classe Calculadora:

namespace Polimorfismo
{
    public enum TipoCalculo
    {
        Adicao,
        Subtracao,
        Multiplicacao,
        Divisao
    }

    static class Calculadora
    {
        /// <summary>
        /// Neste método temos que informar o tipo
        /// de calculo que o mesmo irá fazer
        /// </summary>
        /// <param name="tipo">tipo do calculo feito</param>
        /// <param name="valor1">valor 1 para o calculo </param>
        /// <param name="valor2">valor 2 para o calculo</param>
        /// <returns>resultado da expressão</returns>
        public static double Calcular(TipoCalculo tipo, double valor1, double valor2)
        {
            double resultado = 0;

            //e aqui temos o condicional switch
            switch (tipo)
            {
                case TipoCalculo.Adicao:
                    resultado = valor1 + valor2;
                    break;
                case TipoCalculo.Subtracao:
                    resultado = valor1 - valor2;
                    break;
                case TipoCalculo.Multiplicacao:
                    resultado = valor1 * valor2;
                    break;
                case TipoCalculo.Divisao:
                    resultado = valor1 / valor2;
                    break;
                default:
                    throw new NotImplementedException("nunca poderá chegar aqui");
            }

            return resultado;
        }

        /// <summary>
        /// fazendo deste modo não precisamos
        /// utilizar nenhum condicional
        /// </summary>
        /// <param name="calc">tipo de calculo</param>
        /// <returns>resultado do calculo</returns>
        public static double Calcular(CalculoMatematico calc)
        {
            return calc.Resultado();
        }
    }
}

Exemplificando…

namespace Polimorfismo
{
    class Program
    {
        static void Main(string[] args)
        {
            //aqui vamos usar o condicional
            Console.WriteLine("Usando o Condicional");
            Console.WriteLine(Calculadora.Calcular(TipoCalculo.Adicao, 23, 34).ToString("N2"));
            Console.WriteLine(Calculadora.Calcular(TipoCalculo.Divisao, 23, 34).ToString("N2"));
            Console.WriteLine(Calculadora.Calcular(TipoCalculo.Multiplicacao, 23, 34).ToString("N2"));
            Console.WriteLine(Calculadora.Calcular(TipoCalculo.Subtracao, 23, 34).ToString("N2"));

            Console.WriteLine("".PadLeft(80, '-'));
            Console.WriteLine("Usando polimorfismo");
            //Aqui nao iremos usar o condicional.
            //substituiremos pelo uso do polimorfismo
            CalculoMatematico calc;

            //aqui é criado como Adicao
            calc = new Adicao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(Calculadora.Calcular(calc).ToString("N2"));

            //aqui é criado como Divisao
            calc = new Divisao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(Calculadora.Calcular(calc).ToString("N2"));

            //aqui é criado como Multiplicacao
            calc = new Multiplicacao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(Calculadora.Calcular(calc).ToString("N2"));

            //aqui é criado como Subtracao
            calc = new Subtracao();
            calc.Valor1 = 23;
            calc.Valor2 = 34;
            Console.WriteLine(Calculadora.Calcular(calc).ToString("N2"));

            Console.ReadKey();
        }
    }
}

Na classe Calculadora, além de exemplificarmos a substituição de um condicional com o uso do polimorfismo, ainda vimos a sobrecarga de métodos, temos dois métodos Calcular com assinaturas diferentes.

Para um melhor entendimento de sobrecarga recomendo a leitura do tópico Definições – Intermediário (POO).

E vimos também o item 3 que diz que podemos aceitar parâmetros de várias formas de objetos reparem que o método public static double Calcular(CalculoMatematico calc) aceitou os quatro tipos básicos.

Conclusão

Vimos o uso do polimorfismo em métodos, mas podemos usar a idéia em construtores, propriedades, no uso de Generics (Tipos Genéricos (Generics)), que podemos chamar de Polimorfismo Genérico.

Podemos citar rapidamente o uso de downcast (converter em uma classe mais específica) ,  upcast (definir em uma classe mais genérica).

namespace Polimorfismo
{
    class Program
    {
        static void Main(string[] args)
        {
            //definir objeto
            CalculoMatematico calc = new Adicao();
            calc.Valor1 = 22;
            calc.Valor2 = 33;

            //downcast (classe mais específica)
            Adicao adicao = (Adicao)calc;
            Console.WriteLine(adicao.Resultado());

            //upcast (classe mais genérica)
            calc = (CalculoMatematico)adicao;
            Console.WriteLine(calc.Resultado());

            Console.ReadKey();
        }
    }
}

Ver Índice

É isso ai pessoal 🙂
Até o próximo
♦ Marcelo

About Marcelo

Nascido em Juruaia/MG em uma fazenda de criação de búfalos, e residindo na região Sul do Brasil. Trabalha com desenvolvimento de aplicações desde os 17 anos. Atualmente é Arquiteto Organizacional na Unimake Software. Para saber mais ... http://desenvolvedores.net/marcelo []'s