Usando My.Settings no Visual Basic 2005

Visual Studio 2005

Emad Ibrahim

Optimal Solutions Integration, Inc.

Outubro de 2004

Resumo: Este artigo discute como a classe My.Settings cria aplicativos de armazenamento e configurações de usuário de maneira muito mais simples que no Visual Basic 2005. (11 páginas impressas.)

Observação: este artigo e os exemplos de código se baseiam em uma versão de pré-lançamento do Microsoft Visual Studio 2005, anteriormente denominada "Whidbey". Todas as informações aqui contidas estão sujeitas a alterações.

Introdução

Os aplicativos do Windows Forms exigem dados que são necessários para executar o aplicativo. Na maior parte do tempo, você não deseja incluir esses dados no código, ou você precisará recompilar o aplicativo sempre que fizer uma alteração. Se o aplicativo usar um serviço da Web ou um banco de dados, provavelmente, você desejará armazenar a URL ou a seqüência de conexão em um arquivo separado, de maneira que possa alterá-las facilmente. Se o aplicativo armazena o layout da janela e outra personalização da interface de usuário, então, você deseja armazenar essas informações separadamente para cada usuário.

No passado, esses dados eram armazenados em muitos locais diferentes, como arquivos INI, o Registro ou arquivos de configuração. O Microsoft .NET Framework 1.0 introduziu o conceito de arquivos app.config, que são arquivos XML usados para armazenar tais configurações. Cada um desses métodos tem algumas questões:

  • As configurações não são seguras para digitação.

  • Exige uma quantidade considerável de código (para ler e escrever arquivos, por exemplo).

  • O método de Registro exige que o aplicativo tenha permissões de segurança suficientes para acessar o Registro.

  • É difícil manter as configurações do escopo do usuário para o aplicativo.

A nova arquitetura de configurações de aplicativos orienta essas necessidades, fornecendo uma maneira fácil de armazenar configurações do escopo do aplicativo e do escopo do usuário no cliente. Usando o Visual Studio ou um editor de código, você define uma configuração para uma determinada propriedade, especificando seu nome, tipo de dados, valor padrão e escopo (aplicativo ou usuário).

As configurações de aplicativos funcionam armazenando dados como XML em diferentes arquivos de configuração (.config), dependendo de a configuração ser do escopo do aplicativo ou do usuário. As configurações do escopo do aplicativo são somente leitura. Como as configurações do escopo do aplicativo são informações do programa, normalmente, não será preciso substituí-las. Ao contrário, as configurações do escopo do usuário podem ser lidas e gravadas com segurança em tempo de execução, mesmo se o aplicativo for executado com confiança parcial.

O caminho antigo

O .NET Framework 1.0 introduziu o conceito de arquivos de configuração com o arquivo app.config. O aplicativo usa esse arquivo para armazenar muitas das configurações de aplicativo específicas do seu aplicativo. Este arquivo é um arquivo XML simples que você pode editar facilmente no Bloco de Notas para alterar as configurações do aplicativo ou adicionar novas. Por exemplo, esse é um ótimo lugar para armazenar o endereço do servidor SMTP, de uma seqüência de conexão com o banco de dados, etc. A implementação do .NET Framework 1.0 tem algumas deficiências. Uma deficiência é que não havia maneira fácil de gravar no arquivo. Para alterar as configurações por meio de uma página ou um formulário no aplicativo, você tinha que carregar o arquivo como um XML, alterá-lo e, em seguida, gravá-lo. Outra deficiência era que o acesso às propriedades no arquivo de configuração não era seguro para digitação. Por exemplo, a linha de código a seguir compila com precisão, mas pode causar um erro de tempo de execução, se a configuração de PageSize não for um inteiro (se não for segura para digitação):

Dim PageSize As Integer = 
Configuration.ConfigurationSettings.AppSettings("PageSize")

Não há nada que impeça um usuário ou desenvolvedor de colocar um valor não numérico nessa configuração de aplicativo, como exibido abaixo, resultando em um erro de tempo de execução.

<add key="PageSize" value="ten"/>

O novo e melhor caminho

O .NET Framework 2.0 aborda a maioria dessas deficiências e mais. A primeira coisa que você observará é a facilidade com que pode criar uma nova configuração. Você não precisa abrir o arquivo de configuração e digitar a nova configuração. Em vez disso, você vai para o Settings Designer, no formulário de propriedades do projeto, e adiciona novas configurações. Lá, você pode selecionar o nome, o tipo e o escopo (aplicativo ou usuário) de cada configuração.

Escopo

As configurações no escopo do aplicativo são somente leitura e compartilhadas por todos os usuários desse aplicativo. Essas configurações são armazenadas no arquivo app.config da seção <applicationSettings>.

Observação: isso é diferente da seção <appSettings> mencionada acima e usada no .NET 1.0.

No tempo de execução, o arquivo app.config estará na pasta bin e será denominado com o nome do aplicativo (MySettingsDemo.exe.config). Um exemplo de uma configuração do escopo do aplicativo seria uma seqüência de conexão com o banco de dados, uma URL de serviço da Web, o endereço IP de um servidor, etc.

<applicationSettings>
    <MySettingsDemo.MySettings>
      <setting name="SMTPServerIP" serializeAs="String">
        <value>127.0.0.1</value>
      </setting>
      <setting name="MyServicesURL" serializeAs="String">
        <value>http://localhost/myservices.asmx</value>
      </setting>
    </MySettingsDemo.MySettings>
  </applicationSettings>

As configurações do escopo do usuário são específicas de cada usuário. Elas podem ser lidas e definidas com segurança pelo código do aplicativo em tempo de execução. Essas configurações são armazenadas em um arquivo user.config. Para ser exato tecnicamente, há dois user.configs por usuário por aplicativo — um para não-roaming e um para roaming. Embora a documentação disponível com a versão beta do Visual Basic 2005 estabeleça que o arquivo user.config será denominado de acordo com o nome do usuário (joe.config), esse não é o caso. O arquivo user.config é criado em <c:\Documents and Settings>\<username>\[Local Settings\]Application Data\<companyname>\<appdomainname>_<eid>_<hash>\<version>, onde:

  • <c:\Documents and Settings> é o diretório de dados do usuário, não-roaming (Local Settings acima) ou roaming.

  • <username> é o nome do usuário.

  • <companyname> é o valor de CompanyNameAttribute, se disponível. Caso contrário, ignore esse elemento.

  • <appdomainname> é o AppDomain.CurrentDomain.FriendlyName. Normalmente, o padrão é o nome do .exe.

  • <eid> é a URL, StrongName ou Caminho, baseado na evidência disponível para hash.

  • <hash> é um hash de evidência SHA1 reunido a partir do CurrentDomain, na seguinte ordem de preferência:

    • StrongName

    • URL

      Se nenhum desses estiver disponível, use o caminho do .exe.

  • <version> é a configuração AssemblyVersionAttribute de AssemblyInfo.

Um exemplo de caminho se pareceria com o seguinte:

C:\Documents and Settings\Emad.BROKENOAK\Local Settings\Application 
Data\MySettingsDemo\MySettingsDemo_9cfe5ef1\1.0.0.0

O caminho de exemplo seria aberto como na Figura 1.


Figura 1. Caminho de exemplo

Observação: o local do arquivo de configurações do usuário exibido e discutido é correto para Beta 1, mas o local na versão final do Visual Basic 2005 ainda não está finalizado.

O arquivo user.config é criado automaticamente em tempo de execução na primeira vez em que o aplicativo é executado por um novo usuário e um valor não padrão é definido na configuração do escopo do usuário. Essas configurações são definidas no arquivo app.config da seção <userSettings>. Os valores padrão/iniciais das configurações também são definidos no arquivo app.config. Veja a aparência dele no arquivo app.config:

  <userSettings>
    <MySettingsDemo.MySettings>
      <setting name="LastSearchedItem" serializeAs="String">
        <value />
      </setting>
      <setting name="FormSize" serializeAs="String">
        <value>400, 400</value>
      </setting>
      <setting name="FormLocation" serializeAs="String">
        <value>0, 0</value>
      </setting>
    </MySettingsDemo.MySettings>
  </userSettings>

As configurações do escopo do usuário são ótimas para armazenar as suas preferências do aplicativo, que normalmente são diferentes para cada usuário. Exemplos de configurações de escopo do usuário são as configurações de exibição, como tamanho de fonte, localização da janela, listas MRU, etc.

Essa arquitetura é muito flexível porque permite que o aplicativo armazene configurações e preferências para cada usuário, mesmo se o aplicativo estiver sendo executado em um cenário de confiança parcial.

Criando uma configuração

Vamos pressupor que você tem uma caixa de pesquisa no aplicativo e que deseja armazenar o valor do último item pesquisado. Primeiro, crie a interface de usuário do aplicativo, como mostra a Figura 2.


Figura 2. Criando a interface de usuário da caixa de pesquisa

Agora, crie a configuração da última seqüência do item pesquisado. A caixa de pesquisa concluída se parecerá com a Figura 3.

  1. No Solution Explorer, clique duas vezes em My Project (Meu Projeto).

  2. Clique na guia Settings (Configurações) para exibir o Settings Designer (Designer de Configurações).

  3. Digite o nome, o tipo e o escopo da configuração ("LastSearchedItem", String e User, respectivamente).

  4. Na coluna Value (Valor), digite o valor inicial dessa configuração (O que você gostaria de pesquisar?) ou deixe-a em branco.


    Figura 3. Caixa de pesquisa completa

Bastidores de uma configuração

Quando você adiciona uma nova configuração ao Settings Designer, vários eventos ocorrem no segundo plano. Primeiro, uma entrada é adicionada ao arquivo app.config que define as seções para definir as configurações.

  <configSections>
    <sectionGroup 
name="applicationSettings"type="System.Configuration.ApplicationSettingsGroup, System, 
Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <section name="MySettingsDemo.MySettings" 
type="System.Configuration.ClientSettingsSection, System, 
Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    </sectionGroup>
  </configSections>

Em segundo lugar, as próprias configurações são adicionadas ao arquivo app.config (exibido abaixo). Dependendo do tipo de configurações que você define, pode-se ver uma seção applicationSettings, userSettings e/ou connectionStrings.

<userSettings>
    <MySettingsDemo.MySettings>
      <setting name="LastSearchedItem" serializeAs="String">
        <value />
      </setting>
      <setting name="FormSize" serializeAs="String">
        <value>400, 400</value>
      </setting>
      <setting name="FormLocation" serializeAs="String">
        <value>0, 0</value>
      </setting>
    </MySettingsDemo.MySettings>
  </userSettings>
  <connectionStrings>
    <add name="MySettingsDemo.MySettings.ConnectionString" 
connectionString="Server=TABLET; User ID=sa; Password=1234; 
Database=Northwind; Persist Security Info=True" 
providerName="System.Data.SqlClient" />
  </connectionStrings>
  <applicationSettings>
    <MySettingsDemo.MySettings>
      <setting name="SMTPServerIP" serializeAs="String">
        <value>192.168.2.11</value>
      </setting>
      <setting name="MyServicesURL" serializeAs="String">
        <value>http://localhost/MyServices/Service1.asmx</value>
      </setting>
    </MySettingsDemo.MySettings>
  </applicationSettings>

Acessando as configurações

Agora que já adicionamos uma configuração, é necessário recuperá-la e atualizá-la. Recuperar uma configuração é muito fácil. Você pode recuperá-la assim:

My.Settings.LastSearchedItem

A Figura 4 mostra como os campos de configuração do aplicativo são acessíveis por meio do IntelliSense, facilitando muito a localização do valor de configuração exato que você precisa usar.


Figura 4. Recurso IntelliSense em ação

Outra maneira de usar uma configuração é ligá-la a uma propriedade. Esse procedimento quase não exige código. Por exemplo, você pode ligar a configuração FormLocation à propriedade de localização do formulário.

  • Na janela de propriedades do formulário, expanda Data | (ApplicationSettings) | (PropertyBinding).

  • Localize a propriedade Location e selecione a configuração FormLocation, como mostra a Figura 5.


Figura 5. Selecionando a configuração FormLocation

Esse procedimento criará o código na classe code-behind do designer do formulário:

Me.DataBindings.Add(New System.Windows.Forms.Binding("Location", 
MySettingsDemo.MySettings.Value, "FormLocation", True, 
MySettingsDemo.MySettings.Value.LastSearchedItem, Nothing, 
System.Windows.Forms.BindingUpdateMode.OnPropertyChanged))

Observe o último parâmetro na construção da classe Binding. Isso define o modo de atualização da sua configuração. Você pode atualizá-la na alteração, na validação ou nunca. O código padrão gerado no designer atualiza a configuração na alteração.

Quando você liga configurações a propriedades, não precisa se preocupar com a leitura ou gravação da configuração. A propriedade será definida automaticamente quando necessário e, se o valor mudar, ela será salva automaticamente. Observe como tudo isso é realizado sem escrever uma única linha de código.

Observação: as configurações são salvas automaticamente somente em certos tipos de projeto, como aplicativos do Visual Basic Windows Forms. Em outros casos, como em projetos da Biblioteca de Classes, você precisará chamar explicitamente o método Save da classe My.Settings.

Se a propriedade não estiver listada na janela de ligação de propriedade, você ainda pode alcançar o mesmo resultado usando código. Por alguma razão, a propriedade Size não está disponível como propriedade que pode ser ligada. Essa é uma decisão de design dessa versão, mas a versão final disponibilizará todas as propriedades para ligação. Isso se faz adicionando um novo Binding à coleção DataBindings do formulário. A classe Binding é usada para definir o nome da propriedade, o nome da configuração, o armazenamento de dados e o modo de atualização. Portanto, para ligar a propriedade de tamanho à configuração FormSize, você pode criar a ligação manualmente no seu evento de carregamento de formulário:

Me.DataBindings.Add(New System.Windows.Forms.Binding("Size", _
                    MySettingsDemo.MySettings.Value, _
                    "FormSize"))

Configurações avançadas

Se você deseja mais controle sobre as configurações, pode definir sua própria classe que deriva da ApplicationSettingsBase, que é a classe pai de todas as classes de configuração. Defina cada configuração como uma propriedade com um get e um set definidos. Decore essa propriedade com ApplicationScopedSettingAttribute, se for uma configuração do escopo do aplicativo, ou como UserScopedSettingAttribute, se for uma configuração do escopo do usuário. Realmente, é exatamente isso que o designer de configurações faz. Segue um fragmento do arquivo MySettings.vb gerado pelo designer de configurações:

Partial NotInheritable Class MySettings
    Inherits System.Configuration.ApplicationSettingsBase
 
    <System.Diagnostics.DebuggerNonUserCode(),  _
     System.Configuration.UserScopedSettingAttribute(),  _
     System.Configuration.DefaultSettingValueAttribute("400, 400")>  _
    Public Property FormSize() As System.Drawing.Size
        Get
            Return CType(Me("FormSize"),System.Drawing.Size)
        End Get
        Set
            Me("FormSize") = value
        End Set
    End Property
    
    <System.Diagnostics.DebuggerNonUserCode(),  _
     System.Configuration.SpecialSetting(System.Configuration.SpecialSetting.ConnectionString),  _
     System.Configuration.ApplicationScopedSettingAttribute(),  _
     System.Configuration.DefaultSettingValueAttribute("Server=TABLET; 
User ID=sa; Password=1234; Database=Northwind; Persist Security In"& _ 
        "fo=True")>  _
    Public ReadOnly Property ConnectionString() As String
        Get
            Return CType(Me("ConnectionString"),String)
        End Get
    End Property
    
    <System.Diagnostics.DebuggerNonUserCode(),  _
     System.Configuration.ApplicationScopedSettingAttribute(),  _
     System.Configuration.DefaultSettingValueAttribute("192.168.2.11")>  _
    Public ReadOnly Property SMTPServerIP() As String
        Get
            Return CType(Me("SMTPServerIP"),String)
        End Get
    End Property
...

Observação: as seqüências de conexão são decoradas pelo atributo SpecialSetting. Elas também são criadas em sua própria seção do arquivo de configuração.

Além disso, observe que essa é uma classe Partial, o que significa que você pode criar outro arquivo no projeto e outra parte nessa classe. Usando essa técnica, você pode fazer o ajuste fino das configurações sem tocar no arquivo gerado pelo designer. É possível adicionar a manipulação de eventos a essa classe, para fornecer um controle mais preciso sobre as configurações. Os três eventos que você pode manipular são:

  • SettingChanging

  • SettingsSaving

  • PropertyChanging

É importante observar que os recursos de configuração situam-se sobre uma infra-estrutura de provedor conectável. O Visual Studio 2005 atual inclui somente um provedor — LocalFileSettingsProvider — que pode acessar os arquivos .config. Provedores alternativos podem ser conectados e usados em vez ou além do provedor de configurações de arquivo local. Um bom exemplo disso são as configurações em um cenário nebuloso, onde um serviço da Web é usado para armazenar configurações em um banco de dados, que é, em seguida, buscado de onde quer que o usuário tenha feito logon.

Conclusão

As arquiteturas anteriores para manipulação de configurações de aplicativo tinham algumas limitações, e a nova arquitetura de Application Settings no .NET Framework 2.0 resolve muitas dessas questões. A nova arquitetura simplifica muito a criação, a ligação, a recuperação e a atualização de configurações, como mostrou este artigo com a ajuda do Visual Basic 2005. Ela também orienta as configurações do escopo do aplicativo e do escopo do usuário. Essa nova arquitetura certamente aumentará a produtividade e permitirá que os desenvolvedores se concentrem em resolver os problemas do negócio, em vez de perderem dias ou semanas resolvendo todas as complicações das configurações do aplicativo.

Emad Ibrahim (MCSD, MCAD) é um arquiteto técnico da Optimal Solutions Integration, Inc.

© 2005 Microsoft Corporation. Todos os direitos reservados. Termos de uso.

Mostrar: