domingo, 15 de maio de 2011

Classes Genéricas: Lista Ligada em C#

Esse post não será mais atualizado nesse blog. Para visualizar esse post em seu novo endereço, acesse:
http://milaneze.com.br/post/2011/05/15/Classes-Genericas-Lista-Ligada-em-C.aspx


Estou lendo o livro da certificação em .NET e tem esse exercício no primeiro capítulo: criar uma lista ligada usando classses genéricas em C#. Fiz uma bem rápido e estou postando aqui como um exemplo de classes genéricas (não ligue muito para o algoritmo, por favor).

Essa classe aceita qualquer tipo, mas caso quisesse restringir os tipos que podem ser aceitos, usaria "public class ListaLigada where T : IDisposable", por exemplo, para aceitar somente tipos que implementem a interface IDisposable.

Abaixo, segue o código de exemplo:

public class ListaLigadaNo<T>
{
    private ListaLigadaNo<T> _Proximo;

    public ListaLigadaNo<T> Proximo
    {
        get { return _Proximo; }
        internal set { _Proximo = value; }
    }

    private T _valor;

    public ListaLigadaNo(T valor)
    {
        _valor = valor;
    }

    public override string ToString()
    {
        return _valor.ToString();
    }
}



public class ListaLigada<T>
{
    private ListaLigadaNo<T> _Primeiro;
    private ListaLigadaNo<T> _Ultimo;
    private int _Count;


    public int Count
    {
        get { return _Count; }
    }

    public ListaLigadaNo<T> Ultimo
    {
        get { return _Ultimo; }
    }

    public ListaLigadaNo<T> Primeiro
    {
        get { return _Primeiro; }
    }

    public ListaLigada()
    {
        _Primeiro = null;
        _Ultimo = null;
        _Count = 0;
    }

    public override string ToString()
    {
        StringBuilder _sbRetorno = new StringBuilder();

        ListaLigadaNo<T> _noAtual = _Primeiro;

        while (_noAtual != null)
        {
            _sbRetorno.AppendFormat("{0};", _noAtual.ToString());
            _noAtual = _noAtual.Proximo;
        }

        return _sbRetorno.ToString();
    }

    public void AdicionarPrimeiro(T valor)
    {
        ListaLigadaNo<T> _PrimeiroAux = _Primeiro;
        _Primeiro = new ListaLigadaNo<T>(valor);
        _Primeiro.Proximo = _PrimeiroAux;

        if (_PrimeiroAux == null)
            _Ultimo = _Primeiro;

        _Count++;
    }

    public void AdicionarUltimo(T valor)
    {
        ListaLigadaNo<T> _UltimoAux = _Ultimo;
        _Ultimo = new ListaLigadaNo<T>(valor);
        _Ultimo.Proximo = null;

        if (_UltimoAux == null)
            _Primeiro = _Ultimo;
        else
            _UltimoAux.Proximo = _Ultimo;

        _Count++;
    }

    public void AdicionarDepois(ListaLigadaNo<T> No, T valor)
    {
        if (_Primeiro == null)
        {
            _Primeiro = No;
            _Ultimo = new ListaLigadaNo<T>(valor);
            _Ultimo.Proximo = null;
            _Primeiro.Proximo = _Ultimo;
        }
        else
        {
            ListaLigadaNo<T> _ProxAux = No.Proximo;
            No.Proximo = new ListaLigadaNo<T>(valor);
            No.Proximo.Proximo = _ProxAux;

            if (_ProxAux == null)
                _Ultimo = No.Proximo;
        }

        _Count++;
    }
}


class Program
{
    static void Main(string[] args)
    {
        ListaLigada<int> _ListaLigada = new ListaLigada<int>();

        _ListaLigada.AdicionarUltimo(-2);
        _ListaLigada.AdicionarPrimeiro(0);
        _ListaLigada.AdicionarUltimo(-2);

        for (int i = 1; i <= 100; i++)
            _ListaLigada.AdicionarDepois(_ListaLigada.Ultimo, i);

        _ListaLigada.AdicionarPrimeiro(-1);
        _ListaLigada.AdicionarUltimo(-2);
        

        Console.WriteLine(_ListaLigada.ToString());
        Console.WriteLine("Primeiro: {0}", _ListaLigada.Primeiro.ToString());
        Console.WriteLine("Último: {0}", _ListaLigada.Ultimo.ToString());
        Console.WriteLine("Contagem: {0}", _ListaLigada.Count.ToString());

        Console.ReadLine();
    }
}

domingo, 8 de maio de 2011

Entendendo o maldito Delegate

Esse post não será mais atualizado nesse blog. Para visualizar esse post em seu novo endereço, acesse:
http://milaneze.com.br/post/2011/05/08/Entendendo-o-maldito-Delegate.aspx


Estudando sobre o assunto percebi que o negócio é complicado, mas não é impossível de entender. Quando encontrar páginas que ensinem bem e de forma simples de entender irei postando aqui. Por enquanto o que achei foi:

Delegates in .NET
http://dotnetslackers.com/articles/net/Delegates-in-NET.aspx

sábado, 7 de maio de 2011

IIS 5 e Windows XP: Server Application Unavailable

Esse post não será mais atualizado nesse blog. Para visualizar esse post em seu novo endereço, acesse:
http://milaneze.com.br/post/2011/05/07/IIS-5-e-Windows-XP-Server-Application-Unavailable.aspx


A situação é a seguinte: após configurar tudo no IIS, deixar acesso para usuários anônimos e tudo mais configurado certinho, ainda recebo o seguinte erro ao acessar minha página:

Server Application Unavailable

The web application you are attempting to access on this web server is currently unavailable.  Please hit the "Refresh" button in your web browser to retry your request.

No Event Viewer o erro começa assim: Exception: System.IO.FileLoadException...

Na maioria dos fóruns falam pra dar acesso para o usuário padrão do IIS e coisas do tipo. Eu não imaginava que a solução pra mim pudesse ser tão simples: Compartilhar a pasta na rede. Só isso e consegui acessar minhas páginas normalmente.

Erro: EXECUTE permission denied on object 'sp_sdidebug', database 'master', owner 'dbo'

Esse post não será mais atualizado nesse blog. Para visualizar esse post em seu novo endereço, acesse:
http://milaneze.com.br/post/2011/05/07/Erro-EXECUTE-permission-denied-on-object-sp_sdidebug-database-master-owner-dbo.aspx


Ao debugar uma página ASP.NET eu estava obtendo esse erro: EXECUTE permission denied on object 'sp_sdidebug', database 'master', owner 'dbo'.

Vi várias opções de como arrumar isso, inclusive dando permissão para executar a stored procedure citada no erro (o que pra mim não funcionou). O fórum que realmente me ajudou foi esse:

http://forums.asp.net/t/1179952.aspx/1?Get+quot+EXECUTE+permission+denied+on+object+sp_sdidebug+database+master+owner+dbo+quot+error+when+debugger+attached

Pelo que entendi, o Visual Studio entende, por padrão, que estamos querendo debugar também as stored procedures, por isso "sp_sdidebug" seria necessária. Como não era essa minha intenção, então desabilitei isso: "Property Pages" do site, "Start Options" e abaixo de "Debugger" tirar a opção "SQL Server". Na hora de dar um Attach para debugar, por exemplo, direto do IIS, preste atenção também na opção "Attach to".

Screenshot de uma página web com Flash

Esse post não será mais atualizado nesse blog. Para visualizar esse post em seu novo endereço, acesse:
http://milaneze.com.br/post/2011/05/07/Screenshot-de-uma-pagina-web-com-Flash.aspx


É uma tristeza ter que dar um Print Screen para uma parte da janela do navegador, depois rolar mais um pouco e dar mais um Print Screen, assim sucessivamente até conseguir o screenshot de cada parte da página web. Depois ainda ter que juntar cada pedaço pra gerar uma imagem só para enviar, por exemplo, por e-mail. Triste. Encontrei alguns programas que executam essa tarefa muito bem, menos quando a página tem partes em Flash.

Esses programas geralmente renderizam a página e já criam a imagem da mesma. Geralmente o Flash leva um tempo a mais pra carregar, apesar de já estar renderizado pelo HTML. O resultado é que toda a página aparece já carregada, mas o Flash aparece em branco ou com o vídeo padrão antes de carregar.

Depois de pesquisar um pouco, cito abaixo quatro soluções para esses casos específicos.


Web Shot

Esse programa é muito bom e tem ferramentas que são gratuitas. Ele pode ser baixado no site abaixo:

http://www.websitescreenshots.com/

O truque desse software é renderizar a página e esperar mais um tempo até o conteúdo em flash ser carregado para aí sim efetuar o screenshot. O padrão de espera é de 5 segundos, mas isso pode ser alterado na aba Process do programa. O grande problema nisso é que a ferramenta de renderização usada pelo programa não é tão rápida quanto o IE ou Firefox. Isso significa que 5 segundos de espera no Web Shot não é o mesmo que 5 segundos no Firefox, por exemplo. Na minha máquina (Core i3) 5 segundos no Firefox equivalem a 120 no Web Shot, o que é suficiente para carregar o conteúdo em Flash do FusionCharts. Dependendo da máquina em que for usado, algumas animações simplesmente não irão carregar totalmente e não adianta colocar mais tempo.


Screenshot Pimp

Esse é um add-on do Firefox que, entre outras funcionalidades, gera um screenshot da página. Ele e o FireShot são os únicos que encontrei que conseguem extrair todos os arquivos Flash na imagem, mesmo os que não estão na parte visível da página, apesar que em alguns lugares a imagem do Flash fica preta de qualquer maneira. Os outros add-ons (incluindo o PdfIt, que acho muito bom por gerar PDF também) geram as animações não visíveis na tela com tudo preto. Esse add-on pode ser baixado no link abaixo:

https://addons.mozilla.org/pt-BR/firefox/addon/screenshot-pimp-screengrab-scr/

A vantagem dessa abordagem é que a página já está carregada, assim como as animações em Flash, assim a transformação da página em imagem (.jpg ou .png) é praticamente instantânea. Já a desvantagem é que é necessário o Firefox para funcionar, diferente do Web Shot que é para Windows e não depende de navegador. Além disso, nem toda página fica igual no Firefox e no IE (por descuido do desenvolvedor ou designer).


FireShot

Esse add-on é interessante porque anula esse problema que até o Screenshot Pimp tem às vezes: gerar as imagens do Flash como um retângulo preto (no Firefox 4 fica branco). A idéia dele é rolar a página, assim as imagens em Flash sempre serão tiradas na parte visível da página, evitando o erro de ficarem pretas. Outra vantagem é que ele pode ser encontrado para o IE, Firefox e Chrome.

Ele pode ser encontrado na página dos criadores do plugin:

http://screenshot-program.com/fireshot/


Para Desenvolvedores .NET

Resolvi juntar os exemplos que vi na web e criar uma biblioteca .NET que facilitasse a vida de desenvolvedores que utilizam ASP.NET e querem criar um botão ou link em suas páginas para transformá-las em JPEG. Abaixo coloquei um link com um exemplo em ASP.NET 3.5 de como usar essa DLL:

http://dl.dropbox.com/u/20361010/blog/pagescreenshot/PageToJpg.zip

Assim como o Web Shot, essa biblioteca usa um objeto (nesse caso, o WebBrowser) para renderizar a página e é necessário usar um tempo de espera para carregar o conteúdo em Flash. Os problemas descritos na parte do Web Shot são praticamente os mesmos aqui. Se a página não tiver conteúdo em Flash, tudo funciona bem.