Estou tentando implementar uma seção de configuração personalizada em um projeto e continuo correndo contra exceções que não entendo. Espero que alguém possa preencher os espaços em branco aqui.
Eu tenho App.config
que se parece com isso:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="ServicesSection" type="RT.Core.Config.ServicesConfigurationSectionHandler, RT.Core"/>
</configSections>
<ServicesSection type="RT.Core.Config.ServicesSection, RT.Core">
<Services>
<AddService Port="6996" ReportType="File" />
<AddService Port="7001" ReportType="Other" />
</Services>
</ServicesSection>
</configuration>
Eu tenho um ServiceConfig
elemento definido assim:
public class ServiceConfig : ConfigurationElement
{
public ServiceConfig() {}
public ServiceConfig(int port, string reportType)
{
Port = port;
ReportType = reportType;
}
[ConfigurationProperty("Port", DefaultValue = 0, IsRequired = true, IsKey = true)]
public int Port
{
get { return (int) this["Port"]; }
set { this["Port"] = value; }
}
[ConfigurationProperty("ReportType", DefaultValue = "File", IsRequired = true, IsKey = false)]
public string ReportType
{
get { return (string) this["ReportType"]; }
set { this["ReportType"] = value; }
}
}
E eu tenho um ServiceCollection
definido assim:
public class ServiceCollection : ConfigurationElementCollection
{
public ServiceCollection()
{
Console.WriteLine("ServiceCollection Constructor");
}
public ServiceConfig this[int index]
{
get { return (ServiceConfig)BaseGet(index); }
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
public void Add(ServiceConfig serviceConfig)
{
BaseAdd(serviceConfig);
}
public void Clear()
{
BaseClear();
}
protected override ConfigurationElement CreateNewElement()
{
return new ServiceConfig();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((ServiceConfig) element).Port;
}
public void Remove(ServiceConfig serviceConfig)
{
BaseRemove(serviceConfig.Port);
}
public void RemoveAt(int index)
{
BaseRemoveAt(index);
}
public void Remove(string name)
{
BaseRemove(name);
}
}
A parte que falta é o que fazer para o manipulador. Originalmente, tentei implementar um, IConfigurationSectionHandler
mas encontrei duas coisas:
- não deu certo
- está obsoleto.
Agora estou completamente perdido sobre o que fazer para poder ler meus dados na configuração. Qualquer ajuda por favor!
c#
configuration
app-config
configuration-files
Chris Holmes
fonte
fonte
Respostas:
A resposta anterior está correta, mas também darei todo o código.
Seu app.config deve ficar assim:
Suas aulas
ServiceConfig
eServiceCollection
permanecem inalteradas.Você precisa de uma nova classe:
E isso deve fazer o truque. Para consumi-lo, você pode usar:
fonte
[Add|Remove|Clear]ItemName
propriedades noConfigurationCollection
atributo não são realmente necessárias neste caso, porque "add" / "clear" / "remove" já são os nomes padrão dos elementos XML.Se você estiver procurando por uma seção de configuração personalizada, como a seguir
então você pode usar minha seção de implementação da configuração, para começar, adicione
System.Configuration
referência de montagem ao seu projetoOlhe para cada elemento aninhado que eu usei. O primeiro é Credenciais com dois atributos, então vamos adicioná-lo primeiro
Elemento Credenciais
PrimaryAgent e SecondaryAgent
Ambos têm os mesmos atributos e parecem um endereço para um conjunto de servidores para um primário e um failover; portanto, você só precisa criar uma classe de elemento para os dois, como seguir
Explicarei como usar dois elementos diferentes com uma classe posteriormente neste post. Vamos pular o SiteId, pois não há diferença. Você só precisa criar uma classe igual à anterior com apenas uma propriedade. vamos ver como implementar a coleção Lanes
ele é dividido em duas partes, primeiro você precisa criar uma classe de implementação de elemento e depois criar uma classe de elemento de coleção
LaneConfigElement
você pode observar que um atributo de
LanElement
é uma enumeração e se tentar usar qualquer outro valor na configuração que não esteja definido no aplicativo de enumeração ativará umaSystem.Configuration.ConfigurationErrorsException
inicialização. Ok, vamos para a definição de coleçãovocê pode perceber que eu defini o que
AddItemName = "Lane"
você pode escolher o que quiser para o item de entrada da coleção. Prefiro usar "add" o padrão, mas o alterei apenas para fins deste post.Agora todos os nossos elementos aninhados foram implementados agora, devemos agregar todos os da classe que precisa implementar
System.Configuration.ConfigurationSection
CustomApplicationConfigSection
Agora você pode ver que temos duas propriedades com o nome
PrimaryAgent
eSecondaryAgent
ambas têm o mesmo tipo. Agora você pode entender facilmente por que tínhamos apenas uma classe de implementação nesses dois elementos.Antes de poder usar esta seção de configuração recém-inventada em seu app.config (ou web.config), você só precisa informar ao aplicativo que você inventou sua própria seção de configuração e respeitar um pouco, para isso, é necessário adicionar as seguintes linhas no app.config (pode ser logo após o início da marca raiz).
NOTA: MyAssemblyName deve ficar sem .dll, por exemplo, se o nome do arquivo de montagem for myDll.dll, use myDll em vez de myDll.dll
para recuperar essa configuração, use a seguinte linha de código em qualquer lugar do seu aplicativo
Espero que o post acima o ajude a começar com um tipo um pouco complicado de seções de configuração personalizadas.
Happy Coding :)
**** Editar **** Para ativar o LINQ,
LaneConfigCollection
você precisa implementarIEnumerable<LaneConfigElement>
E adicione a seguinte implementação de
GetEnumerator
para as pessoas que ainda estão confusas sobre como o rendimento realmente funciona, leia este belo artigo
Dois pontos-chave extraídos do artigo acima são
fonte
Este é um código genérico para a coleção de configurações:
Depois de ter
GenericConfigurationElementCollection
, você pode simplesmente usá-lo na seção de configuração (este é um exemplo do meu Dispatcher):O elemento Config é config Here:
O arquivo de configuração ficaria assim:
Espero que ajude!
fonte
Uma alternativa mais fácil para quem prefere não escrever manualmente toda essa configuração manualmente ...
1) Instale o Nerdle.AutoConfig partir do NuGet
2) Defina seu tipo de ServiceConfig (uma classe concreta ou apenas uma interface, também serve)
3) Você precisará de um tipo para armazenar a coleção, por exemplo
4) Adicione a seção de configuração da seguinte maneira (observe a nomeação camelCase)
5) Mapa com AutoConfig
fonte
Tente herdar do ConfigurationSection . Esta postagem no blog de Phil Haack tem um exemplo.
Confirmado, de acordo com a documentação para IConfigurationSectionHandler :
fonte