views:

86

answers:

4

I'm importing some XML to C#, and want to be able to access data from the XML in the form of what I think is a nested structure. (I may be wrong!)

What I have in my XML is in the following form:

<hardwareSettings initial="true>
    <cameraSettings width="1024" height="768" depth="8" />
    <tiltSettings theta="35" rho="90">
</hardwareSettings>

I can import each setting alright, so I have them all in individual ints, but I would like to be able to access it in the form

int x=hardwaresettings.camerasettings.width;
int rho=hardwaresettings.tiltsettings.rho;

I've tried various arrangements of structs within structs, but I don't seem able to cast a new object (hardwaresettings) that contains the appropriate children (camerasettings.width & tiltsettings.rho).

Sorry if I'm not using the right lingo... I'm reading myself in circles here!

A: 

You can implement such functionality by writing custom wrapper over XDocument class.

Andrew Bezzub
+1  A: 
public class TiltSettings
{
    public TiltSettings(XElement element)
    {
        this.Theta = Convert.ToInt32(element.Attribute("theta").Value);
        this.Rho = Convert.ToInt32(element.Attribute("rho").Value);
    }
    public int Theta {get; set;}
    public int Rho { get; set; }
}
public class CameraSettings
{
    public CameraSettings(XElement element)
    {
        this.Height = Convert.ToInt32(element.Attribute("height").Value);
        this.Width = Convert.ToInt32(element.Attribute("width").Value);
        this.Depth = Convert.ToInt32(element.Attribute("depth").Value);
    }
    public int Width {get; set;}
    public int Height {get; set;}
    public int Depth { get; set; }
}
public class HardwareSettings
{
    public HardwareSettings(string xml)
    {
        var xDoc = XDocument.Parse(xml);
        this.IsInitial = xDoc.Root.Attribute("initial").Value == "true";
        this.Camera = new CameraSettings(xDoc.Root.Element("cameraSettings"));
        this.Tilt = new TiltSettings(xDoc.Root.Element("tiltSettings"));
    }
    public CameraSettings Camera {get; set;}
    public TiltSettings Tilt {get; set;}
    public bool IsInitial {get; set;}
}
Software.Developer
This is exactly what I tried about half an hour ago... but when I cast a new object of HardwareSettings, I can't reference the children - i.e. after casting "HardwareSettings HS=new HardwareSettings(xml);" "HS.CameraSettings.Width" doesn't work...
zotty
I edited my answer now that I have a better idea of what you're looking for. Also, when you say 'cast a new object', I think you mean 'instantiate a new object'. =)
Software.Developer
This worked a treat - thanks everso much!
zotty
A: 

probably something similar would work, if I have got your question right.


class HardwareSettings
{
    public TiltSettings TiltSettings { get; set; }
    public CameraSetting CameraSetting { get; set; }
}

    struct CameraSetting
    {
        public int Width { get; set; }    
        public int Height { get; set; }
        public int Depth { get; set; }
    }

    struct TiltSettings
    {
        public int Theta { get; set; }
        public int Rho { get; set; }
    }

EDIT:


To access class "properties"as: HardwareSettings.CameraSetting.Depth

    XElement elements = XElement.Load("XMLFile.xml");
    List<HardwareSettings> hardwareSettingsList =
                (from e in elements.Descendants("cameraSettings")
                select new HardwareSettings
                {
                    CameraSetting = new CameraSetting()
                        {
                            Depth = Convert.ToInt32(e.Attribute("width").Value),
                            Height = Convert.ToInt32(e.Attribute("width").Value),
                            Width = Convert.ToInt32(e.Attribute("width").Value)
                        },

                    TiltSettings = new TiltSettings() 
                        { } // your logic for rest of the structs

                }).ToList<HardwareSettings>();

    int depth = 0;
    foreach (HardwareSettings hardwareSetting in hardwareSettingsList)
    {
        depth = hardwareSetting.CameraSetting.Depth;
    }
Asad Butt
This is 90% of the way there... but I want CameraSetting to be a child of HardwareSettings - so I can access it like "int depth=hardwareSetting.cameraSetting.depth;"
zotty
Also, if I may ask, here you cast a new CameraSetting in a very clever way, but I can't figure out how to call it... if I want to recover the value of the depth, I can't call results.CameraSetting... how do I do that?
zotty
Have made editions, try it now, hope this helps
Asad Butt
A: 

Consider creating a settings class and using the built in or custom SettingsProvider.

You would create the class and inherit ApplicationSettingsBase

There is a lot of documentation on this but here is a very quick snippit.

Settings Class

internal sealed partial class TestSettings : ApplicationSettingsBase
{

    private static TestSettings settings = ((TestSettings)(ApplicationSettingsBase.Synchronized(new TestSettings())));

    public static TestSettings Settings { get { return settings; } }

    [UserScopedSetting()]
    public CameraSettingsClass CameraSettings
    {
        get
        {
            try
            {
                if(this["CameraSettings"] == null) return (CameraSettingsClass)(new CameraSettingsClass());
                else return (CameraSettingsClass)this["CameraSettings"];
            }
            catch(Exception error) {throw new Exception("Problem with accessing CameraSettings");}
        }
        set { this["CameraSettings"] = value; }
    }
}
    public class CameraSettingsClass
    {
        [XmlAttribute]
        public int Width {get;set;}
        [XmlAttribute]
        public int Height {get;set;}
        [XmlAttribute]
        public int Depth {get;set;}
        public CameraSettingsClass()
        {
            this.Width = 1024;
            this.Height = 768;
            this.Depth = 8;
        }
    }

//Access of the settings as follows
TestSettings.Settings.CameraSettings
//or
TestSettings.Settings["CameraSettings"]

XML Output for the Node

<TestProject.TestSettings>
    <setting name="CameraSettings" serializeAs="Xml">
        <value>
            <CameraSettingsClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema" Width="512" Height="768"
                Depth="8" />
        </value>
    </setting>
</TestProject.TestSettings>

You can checkout more information here about the details of using the Different SettingsProviders http://msdn.microsoft.com/en-us/library/ms171565(VS.80).aspx

Using a settings provider and ApplicationSettingsBase will give you .Save() .Reload() .Upgrade() etc.. functionality.

galford13x