Search code examples
c#xmllinqsystem.reflection

Read XML node using reflection c#


I have this function to read xml values and create an instance of a class.

Is there a way to combine linq and reflection to not specify the properties of the class and create the class with less code lines?

I try to avoid to modify this method if I add or remove some fields to Test_Class

    /// <summary>
    /// Get the values of a xml node and return a class of type Class_Test
    /// </summary>
    /// <param name="sXmlFileName">Path to xml file.</param>
    /// <param name="sNodeName">Name of node to get values.</param>
    /// <returns>Class_Test New class with the values set from XML.</returns>
    public static Class_Test Func_ReadXMLNode(string sXmlFileName, string sNodeName)
    {
        //Load XML
        XDocument xml_Document;
        Class_Test result;
        try
        {
            xml_Document = XDocument.Load(sXmlFileName);
            //Read XML Section
            var xmlValues = from r in xml_Document.Descendants(sNodeName)
                            select new Class_Test
                            {
                                sNetworkInterfaceName = Convert.ToString(r.Element("").Value),
                                iNetworkInterfacePort = Convert.ToInt32(r.Element("").Value),
                                sCertificateFile = Convert.ToString(r.Element("").Value),
                                sCertificateName = Convert.ToString(r.Element("").Value),
                                iKeepAliveSendingTime = Convert.ToInt32(r.Element("").Value),
                                iMaximumTimeWithoutKeepAlive = Convert.ToInt32(r.Element("").Value),
                                sSqlServer = Convert.ToString(r.Element("").Value),
                                sDatabase = Convert.ToString(r.Element("").Value),
                                iFtpRetries = Convert.ToInt32(r.Element("").Value),
                                sDetectionFilesDirectory = Convert.ToString(r.Element("").Value),
                                sImgDirectory = Convert.ToString(r.Element("").Value),
                                sLocalDirectory = Convert.ToString(r.Element("").Value),
                                sOffenceDirectory = Convert.ToString(r.Element("").Value),
                                sTmpDirectory = Convert.ToString(r.Element("").Value)
                            };

            result = xmlValues.FirstOrDefault();

        }
        catch (IOException Exception1)
        {
            LogHelper.Func_WriteEventInLogFile(DateTime.Now.ToLocalTime(), enum_EventTypes.Error, "Func_ReadXMLConfig()", "Source = " + Exception1.Source.Replace("'", "''") + ", Message = " + Exception1.Message.Replace("'", "''"));
            result = new Class_Test();
        }

        return result;
    }

And this is Class_Text:

/// <summary>
/// Class of operation mode.
/// </summary>
public class Class_OperationMode
{
    #region CONFIG_PARAMETERS
    /// <summary>
    /// Name of the network interface.
    /// </summary>
    public string sNetworkInterfaceName;
    /// <summary>
    /// Port of the network interface.
    /// </summary>
    public int iNetworkInterfacePort;
    /// <summary>
    /// Path to certificate file.
    /// </summary>
    public string sCertificateFile;
    /// <summary>
    /// Name of the certificate.
    /// </summary>
    public string sCertificateName;
    /// <summary>
    /// Time to keep alive the connection while sending data.
    /// </summary>
    public int iKeepAliveSendingTime;
    /// <summary>
    /// Time before timeout of the connection.
    /// </summary>
    public int iMaximumTimeWithoutKeepAlive;
    /// <summary>
    /// Database server instance.
    /// </summary>
    public string sSqlServer;
    /// <summary>
    /// Path to .mdf file of database.
    /// </summary>
    public string sDatabase;
    /// <summary>
    /// Max retries to try to connect to FTP Server.
    /// </summary>
    public int iFtpRetries;
    /// <summary>
    /// Path to detections files directory.
    /// </summary>
    public string sDetectionFilesDirectory;
    /// <summary>
    /// Path to images directory.
    /// </summary>
    public string sImgDirectory;
    /// <summary>
    /// Path to local directory.
    /// </summary>
    public string sLocalDirectory;
    /// <summary>
    /// Path to folder where save and retrieve offences.
    /// </summary>
    public string sOffenceDirectory;
    /// <summary>
    /// Path to temp directory.
    /// </summary>
    public string sTmpDirectory;

    #endregion

UPDATE: Thanks to comments, I updated code to:

public static Class_Test Func_ReadXMLNode(string sXmlFileName, string sNodeName){
//Load XML
XDocument xml_Document;
Class_Test result;
try
{
    xml_Document = XDocument.Load(sXmlFileName);
    //Read XML Section

    //Get xml values of descendants
    XElement xmlValues = xml_Document.Descendants(sNodeName).FirstOrDefault();
    //Create serializer
    XmlSerializer serializer = new XmlSerializer(typeof(Class_Test));

    //Deserialize 
    using (XmlReader reader = xmlValues.CreateReader())
    {
        result = (Class_Test)serializer.Deserialize(reader);
    }

}
catch (IOException Exception1)
{
    LogHelper.Func_WriteEventInLogFile(DateTime.Now.ToLocalTime(), enum_EventTypes.Error, "Func_ReadXMLConfig()", "Source = " + Exception1.Source.Replace("'", "''") + ", Message = " + Exception1.Message.Replace("'", "''"));
    result = new Class_Test();
}

return result;
}

Thanks in advance. Best regards,

Joaquín


Solution

  • I think what youre looking for is serialization/deserialization. Theres lots of useful stuff in .net for handling xml serialization. Ive stolen this example from the docs (link underneath).

        XmlSerializer serializer = new
        XmlSerializer(typeof(OrderedItem));
    
        // A FileStream is needed to read the XML document.
        FileStream fs = new FileStream(filename, FileMode.Open);
        XmlReader reader = XmlReader.Create(fs);
    
        // Declare an object variable of the type to be deserialized.
        OrderedItem i;
    
        // Use the Deserialize method to restore the object's state.
        i = (OrderedItem)serializer.Deserialize(reader);
        fs.Close();
    

    From https://msdn.microsoft.com/en-us/library/tz8csy73(v=vs.110).aspx