Representando um arquivo de configuração XML com uma classe ixmlSerializable
-
27-09-2019 - |
Pergunta
Estou escrevendo em C# e tentando representar um arquivo de configuração XML através de um IXmlSerializable
classe. Não tenho certeza de como representar os elementos aninhados no meu arquivo de configuração, como logLevel
:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<logging>
<logLevel>Error</logLevel>
</logging>
<credentials>
<user>user123</user>
<host>localhost</host>
<password>pass123</password>
</credentials>
<credentials>
<user>user456</user>
<host>my.other.domain.com</host>
<password>pass456</password>
</credentials>
</configuration>
Há um enume LogLevel
isso representa todos os valores possíveis para o logLevel
marcação. As tags dentro credentials
todos devem sair como cordas. Na minha classe, chamado DLLConfigFile
, Eu tive o seguinte:
[XmlElement(ElementName="logLevel", DataType="LogLevel")]
public LogLevel LogLevel;
No entanto, isso não vai funcionar porque <logLevel>
não está dentro do nó raiz do arquivo XML, é um nó mais fundo <logging>
. Como faço para fazer isso?
Quanto ao <credentials>
nós, meu palpite é que vou precisar de uma segunda aula, digamos CredentialsSection
, e ter uma propriedade como a seguinte:
[XmlElement(ElementName="credentials", DataType="CredentialsSection")]
public CredentialsSection[] AllCredentials;
Editar: Ok, eu tentei a sugestão de Robert Love e criei um LoggingSection
classe. No entanto, meu teste falha:
var xs = new XmlSerializer(typeof(DLLConfigFile));
using (var stream = new FileStream(_configPath, FileMode.Open,
FileAccess.Read, FileShare.Read))
{
using (var streamReader = new StreamReader(stream))
{
XmlReader reader = new XmlTextReader(streamReader);
var file = (DLLConfigFile)xs.Deserialize(reader);
Assert.IsNotNull(file);
LoggingSection logging = file.Logging;
Assert.IsNotNull(logging); // fails here
LogLevel logLevel = logging.LogLevel;
Assert.IsNotNull(logLevel);
Assert.AreEqual(EXPECTED_LOG_LEVEL, logLevel);
}
}
O arquivo de configuração com o qual estou testando definitivamente <logging>
. Aqui está como as aulas são:
[Serializable]
[XmlRoot("logging")]
public class LoggingSection : IXmlSerializable
{
public XmlSchema GetSchema()
{
return null;
}
[XmlElement(ElementName="logLevel", DataType="LogLevel")]
public LogLevel LogLevel;
public void ReadXml(XmlReader reader)
{
LogLevel = (LogLevel)Enum.Parse(typeof(LogLevel),
reader.ReadString());
}
public void WriteXml(XmlWriter writer)
{
writer.WriteString(Enum.GetName(typeof(LogLevel), LogLevel));
}
}
[Serializable]
[XmlRoot("configuration")]
public class DLLConfigFile : IXmlSerializable
{
[XmlElement(ElementName="logging", DataType="LoggingSection")]
public LoggingSection Logging;
}
Solução
Crie uma subclasse que tenha uma única propriedade LogLevel
e, em seguida, crie uma propriedade de registro na sua classe base que é do novo tipo.