Ken Rea
Ken Rea

Reputation: 67

C# Set variable using string that has variable name inside

*Switched over to serailization.

Summary: I have all the variables pre-defined as null / 0. I want to set them using data from and XML document. The document contains the exact same names as the variables. I don't want to use a bunch of else ifs so I'm trying to do it based on the names I pull from the XML document.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Xml;
using System.IO;

public class ShipAttributes
{
    // Model Information
    string name;
    string modelName;
    string firingPosition;
    string cameraPosition;
    string cargoPosition;
    Vector3 cameraDistance;

    // Rotation
    float yawSpeed;
    float pitchSpeed;
    float rollSpeed;

    // Speed
    float maxSpeed;
    float cruiseSpeed;
    float drag;
    float maxAcceleration;
    float maxDeceleration;

    // Physics Properties
    float mass;

    // Collection Capacity
    float cargoSpace;

    // Combat [Defense]
    float structureHealth;
    float armorHealth;
    float shieldHealth;
    float shieldRadius;

    // Combat [Assault]
    float missileRechargeTime;
    float fireRate; 

    // Currency Related
    float cost;
    float repairMultiplier;

void PopulateShipList()
{
    if (shipList != null)
        return;

    string filepath = Application.dataPath + "/Resources/shipsdata.xml";

    XmlRootAttribute xml_Root = new XmlRootAttribute();
    xml_Root.ElementName = "SHIPS";
    xml_Root.IsNullable = true;
    //using (var stream = new FileStream(filepath, FileMode.Open, FileAccess.Read)) 
    //{
        StringReader stringReader = new StringReader(filepath);
        stringReader.Read();
        XmlReader xRdr = XmlReader.Create(stringReader);
        XmlSerializer xml_s = new XmlSerializer(typeof(List<ShipAttributes>), xml_Root);
        shipList= (List<ShipAttributes>)xml_s.Deserialize(xRdr);
    //}
}
public ShipAttributes LoadShip(string inName)
{
    PopulateShipList();
    foreach (ShipAttributes att in shipList)
    {
        if (att.name == inName)
        {
            att.shipList = shipList;
            return att;
        }
    }

    return null;
}

*Note Variables in the XML files have the exact same Format and Name as the variables in the class. maxSpeed in Class is maxSpeed in XML file.

My XML looks like this --

<?xml version="1.0" encoding="UTF-8 without BOM" ?>

     <SHIPS>
        <SHIP>
            <name>Default</name>
            <id>0</id>
            <modelName>Feisar_Ship</modelName>
            <firingPosition>null</firingPosition>
            <cameraPosition>null</cameraPosition>
            <cargoPosition>null</cargoPosition>
            <cameraDistance>null</cameraDistance>
            <yawSpeed>2000.0</yawSpeed>
            <pitchSpeed>3000.0</pitchSpeed>
            <rollSpeed>10000.15</rollSpeed>
            <maxSpeed>200000.0</maxSpeed>
            <cruiseSpeed>100000.0</cruiseSpeed>
            <drag>0.0</drag>
            <maxAcceleration>null</maxAcceleration>
            <maxDeceleration>null</maxDeceleration>
            <mass>5000.0</mass>
            <cargoSpace>150.0</cargoSpace>
            <structureHealth>100.0</structureHealth>
            <armorHealth>25.0</armorHealth>
            <shieldHealth>25.0</shieldHealth>
            <shieldRadius>30.0</shieldRadius>
            <missileRechargeTime>2.0</missileRechargeTime>
            <fireRate>0.5f</fireRate>
            <cost>0</cost>
            <repairMultiplier>1.0</repairMultiplier>
        </SHIP>   
     </SHIPS

>

Yes Yes I know... Feisar! Just place holders for now from turbosquid.

Upvotes: 0

Views: 1460

Answers (2)

Brian Kintz
Brian Kintz

Reputation: 1993

Create a class to hold the values you are reading in and use XML Serialization.

Microsoft Tutorial

Tech Pro Tutorial

MSDN: XmlSerializer

EDIT :

If the XML is exactly the same as the class code you posted, the following should allow you to get a class of ShipAttributes:

ShipAttributes attributes = null;
string filepath = "/path/to/xml";

using (var stream = new FileStream(filepath, FileMode.Open, FileAccess.Read)) {
    var xml_s = new XmlSerializer(typeof(ShipAttributes));

    attributes = (ShipAttributes)xml_s.Deserialize(stream);
}

Edit 2 : Multiple Ships

In your comment, you said that the file contains multiple ShipAttribute descriptions. The way to handle that is the same as above, but deserialize the file into the type List<ShipAttribute> as follows:

List<ShipAttributes> ships = null;
string filepath = "/path/to/xml";

using (var stream = new FileStream(filepath, FileMode.Open, FileAccess.Read)) {
    var xml_s = new XmlSerializer(typeof(List<ShipAttributes>));

    ships= (List<ShipAttributes>)xml_s.Deserialize(stream);
}

Once you've done that, you have all of the ships in memory and can pick the one out of the list you need using Linq etc.

Upvotes: 3

Chief
Chief

Reputation: 914

ASSUMING YOU XML FILE

<?xml version="1.0" encoding="utf-8"?>
<Variables>      
    <VariableName1>1</VariableName1>
    <VariableName2>test</VariableName2>
    <VariableName3>test2</VariableName3>    
</Variables>



var data = XDocument.Load("YourXML.xml");
var xmldata = from x in data.Descendants("Variables")                        
                        select x;

notes.Select(_BuildPropertyFromElement);



private Yourclassname _BuildNoteFromElement(XElement element)
    {
      var type = typeof(**Yourclassname**);
      var Details = new Yourclassname();

      foreach (var propInfo in type.GetProperties())
      {
         var rawValue = element.Element(propInfo.Name).Value;
         var convertedValue = propInfo.PropertyType == typeof(DateTime) ?         (object)Convert.ToDateTime(rawValue) : rawValue;
            propInfo.SetValue(Details , convertedValue, null);
                }

                return Details ;
            }

YOURCLASSNAME is the name of the class which would have all the properties you want to set to

Upvotes: 0

Related Questions