Se você estiver procurando por uma seção de configuração personalizada, como a seguir
<CustomApplicationConfig>
<Credentials Username="itsme" Password="mypassword"/>
<PrimaryAgent Address="10.5.64.26" Port="3560"/>
<SecondaryAgent Address="10.5.64.7" Port="3570"/>
<Site Id="123" />
<Lanes>
<Lane Id="1" PointId="north" Direction="Entry"/>
<Lane Id="2" PointId="south" Direction="Exit"/>
</Lanes>
</CustomApplicationConfig>
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 projeto
Olhe para cada elemento aninhado que eu usei. O primeiro é Credenciais com dois atributos, então vamos adicioná-lo primeiro
Elemento Credenciais
public class CredentialsConfigElement : System.Configuration.ConfigurationElement
{
[ConfigurationProperty("Username")]
public string Username
{
get
{
return base["Username"] as string;
}
}
[ConfigurationProperty("Password")]
public string Password
{
get
{
return base["Password"] as string;
}
}
}
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
public class ServerInfoConfigElement : ConfigurationElement
{
[ConfigurationProperty("Address")]
public string Address
{
get
{
return base["Address"] as string;
}
}
[ConfigurationProperty("Port")]
public int? Port
{
get
{
return base["Port"] as int?;
}
}
}
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
public class LaneConfigElement : ConfigurationElement
{
[ConfigurationProperty("Id")]
public string Id
{
get
{
return base["Id"] as string;
}
}
[ConfigurationProperty("PointId")]
public string PointId
{
get
{
return base["PointId"] as string;
}
}
[ConfigurationProperty("Direction")]
public Direction? Direction
{
get
{
return base["Direction"] as Direction?;
}
}
}
public enum Direction
{
Entry,
Exit
}
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á uma System.Configuration.ConfigurationErrorsException
inicialização. Ok, vamos para a definição de coleção
[ConfigurationCollection(typeof(LaneConfigElement), AddItemName = "Lane", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class LaneConfigCollection : ConfigurationElementCollection
{
public LaneConfigElement this[int index]
{
get { return (LaneConfigElement)BaseGet(index); }
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
public void Add(LaneConfigElement serviceConfig)
{
BaseAdd(serviceConfig);
}
public void Clear()
{
BaseClear();
}
protected override ConfigurationElement CreateNewElement()
{
return new LaneConfigElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((LaneConfigElement)element).Id;
}
public void Remove(LaneConfigElement serviceConfig)
{
BaseRemove(serviceConfig.Id);
}
public void RemoveAt(int index)
{
BaseRemoveAt(index);
}
public void Remove(String name)
{
BaseRemove(name);
}
}
você 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
public class CustomApplicationConfigSection : System.Configuration.ConfigurationSection
{
private static readonly ILog log = LogManager.GetLogger(typeof(CustomApplicationConfigSection));
public const string SECTION_NAME = "CustomApplicationConfig";
[ConfigurationProperty("Credentials")]
public CredentialsConfigElement Credentials
{
get
{
return base["Credentials"] as CredentialsConfigElement;
}
}
[ConfigurationProperty("PrimaryAgent")]
public ServerInfoConfigElement PrimaryAgent
{
get
{
return base["PrimaryAgent"] as ServerInfoConfigElement;
}
}
[ConfigurationProperty("SecondaryAgent")]
public ServerInfoConfigElement SecondaryAgent
{
get
{
return base["SecondaryAgent"] as ServerInfoConfigElement;
}
}
[ConfigurationProperty("Site")]
public SiteConfigElement Site
{
get
{
return base["Site"] as SiteConfigElement;
}
}
[ConfigurationProperty("Lanes")]
public LaneConfigCollection Lanes
{
get { return base["Lanes"] as LaneConfigCollection; }
}
}
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).
<configSections>
<section name="CustomApplicationConfig" type="MyNameSpace.CustomApplicationConfigSection, MyAssemblyName" />
</configSections>
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
CustomApplicationConfigSection config = System.Configuration.ConfigurationManager.GetSection(CustomApplicationConfigSection.SECTION_NAME) as CustomApplicationConfigSection;
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
public new IEnumerator<LaneConfigElement> GetEnumerator()
{
int count = base.Count;
for (int i = 0; i < count; i++)
{
yield return base.BaseGet(i) as LaneConfigElement;
}
}
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
realmente não termina a execução do método. yield return pausa a execução do método e na próxima vez que você o chamar (para o próximo valor de enumeração), o método continuará sendo executado a partir da última chamada de retorno de rendimento. Parece um pouco confuso, eu acho ... (Shay Friedman)
O rendimento não é um recurso do tempo de execução .Net. É apenas um recurso da linguagem C # que é compilado no código IL simples pelo compilador C #. (Lars Corneliussen)