Saving a Class of my variables to XML File - c#

I have created a Class called "VNCVars.cs" and I want to be able to Save the data associated with all the Variables inside VNCVars to a XML file so I can load them back in on startup. I have another class called "SaveData.cs" which contains the code to generate the XML file.
I have code written that runs but my XML file is always empty.....can somebody point out what I have missed out??
public class VNCVars
{
//Global Variables for VNC 1 Location
//VNC File Location 1 Get and Set routines
private static string strVNC1Location;
public static string VNC1Location
{
get { return strVNC1Location; }
set { strVNC1Location = value; }
}
//Global Variables for VNC 2 Location
//VNC File Location 2 Get and Set routines
private static string strVNC2Location;
public static string VNC2Location
{
get { return strVNC2Location; }
set { strVNC2Location = value; }
}
//Global Variables for VNC 3 Location
//VNC File Location 3 Get and Set routines
private static string strVNC3Location;
public static string VNC3Location
{
get { return strVNC3Location; }
set { strVNC3Location = value; }
}
}
public class SaveXML
{
public static void SaveData()
{
var SaveData = new VNCVars();
XmlSerializer sr = new XmlSerializer(typeof(VNCVars));
TextWriter writer = new StreamWriter(#"c:\Fanuc\SetupVars.xml");
sr.Serialize(writer, SaveData);
writer.Close();
}
}
Then finally on my form I currently just have a button and on the click the following occurs...
private void button2_Click(object sender, EventArgs e)
{
SaveXML.SaveData();
}
Any help greatly appreciated....

You should use instance properties instead of static properties.
You can then use the singleton pattern to keep only one instance of this class.

If you need to have static variables and don't want to make this class a singleton, the way around is to wrap static variables:
[XmlElement("VNC1Location")]
public string VNC1LocationLocal
{
get
{
return VNC1Location;
}
set
{
VNC1Location = value;
}
}

Related

How can i Access a private variable in another class in C#

I wrote the code below and i want to access the private varibale in another class, i created instance of the class and tried to access it but couldn't. can someone point out what I did wrong in the code below?
using System;
namespace lab_first
{
public class AccessModifiers
{
private int Abc { get; set; }
private int bcd { get; set; }
}
class Program
{
static void Main(string[] args)
{
var acc = new AccessModifiers();
Console.WriteLine(acc.Abc)
}
}
}
You make members private so that nobody outside the class can access them.
This goes inline with the principle of information hiding.
Your example should look like this:
public class AccessModifiers
{
// You can only access this inside of the class AccessModifiers
private int Abc { get; set; }
internal void SetValue(int x){
// Access possible, because SetValue() is inside the same class
Abc = x;
}
internal int GetValue(){
// Access possible, because GetValue() is inside the same class
return Abc;
}
}
class Program
{
static void Main(string[] args)
{
var acc = new AccessModifiers();
// Abc is never modified directly, only indirectly.
acc.SetValue(5);
Console.WriteLine(acc.GetValue());
}
}
However, there is still a way to access the private member. It's called Reflection. However, note that private variables are considered an implementation detail and might change at any time, so you can't rely on it. E.g. someone might change the name from Abc to def and your Reflection-based approach fails.
You can either change private to internal or public in this case.
Another way is declaring the variables in the class as private and using C# Properties in the class to set and get the values of variables. this is called encapsulation which is a protective shield that prevents the data from being accessed by the code outside this shield).
public class AccessModifiers
{
private int _abc { get; set; }
private int _bcd { get; set; }
public int Abc
{
get
{
return _abc;
}
set
{
_abc = value;
}
}
public int Bcd
{
get
{
return _bcd;
}
set
{
_bcd = value;
}
}
}

Unity + Ink/Inkle: How to load a saved story state JSON

So in our visual novel game using the ink/inkle API for unity, I'm trying to implement a save and load system, but I am currently having trouble with loading the saved state the way I intend to.
Based on the API's documentation, to save the state of your story within your game, you call:
string savedJson = _inkStory.state.ToJson();
then to load it:
_inkStory.state.LoadJson(savedJson);
Here is the how I save the current state of the story using PlayerPrefs, which is working just fine.
public void saveGame()
{
DialogueSystem dialogueSystem = GetComponent<DialogueSystem>();
dialogueSystem.savedJson = dialogueSystem.dialogue.state.ToJson();
PlayerPrefs.SetString("saveState", dialogueSystem.savedJson);
Debug.Log(dialogueSystem.savedJson);
}
and here is how I'm trying to load the saved state on Start(), which doesn't load the saved state.
private void Start()
{
dialogue = new Story(dialogueJSON.text);
currentActiveBG = BGs[0];
historyScript = GetComponent<History>();
counterScript = GetComponent<counter>();
if (PlayerPrefs.HasKey("saveState")) { // for loading the saved state
dialogue = new Story(dialogueJSON.text);
savedJson = PlayerPrefs.GetString("saveState");
dialogue.state.LoadJson(savedJson);
loadLine(); //this function contains story.Continue, which loads the next line
Debug.Log(savedJson);
}
else {
loadGame("Pre_Prep1"); // default starting line
}
}
How can I make this work? And is there a better way of implementing this save/load feature?
I'm not sure which game you're going to make but, I use the following saving system in my project and it's working perfectly and you can also use it.
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Saving System
public class UserData{
#region Save Data Var's
// file Path
private static readonly string FILE_PATH = Application.dataPath +
"/SaveFiles";
public int carToLoad;
public int levelToLoad;
public int unlockLevels;
#endregion
#region Methods
// Save
public static void SaveData(string contents){ // for Car Selection
File.WriteAllText(FILE_PATH + "/UserData.txt",contents);
}
// Load
public static UserData LoadData(){
string _data = File.ReadAllText(FILE_PATH + "/UserData.txt");
return JSONToUserData(_data);
}
// Init
public static void UserData_init(){
CheckFilesPreviousData();
CheckDirectory();
}
// Selection Level Data
public static void SaveData(UserData LevelData) { // for Level
UserData tempObj = LoadData();
tempObj.levelToLoad = LevelData.levelToLoad;
SaveData(UserDataToJSON(tempObj));
}
// UnLock Level Data
public static void SaveUnLockedLevelData(int LevelValue){
UserData tempObj = LoadData();
tempObj.unlockLevels = LevelValue;
File.WriteAllText(FILE_PATH + "/UnLockLevels.text",
UserDataToJSON(tempObj));
}
// Load UnLock Level Data
public static UserData LoadUnLockLevelData(){
string _data= File.ReadAllText(FILE_PATH+"/UnLockLevels.text");
UserData tempObj = JSONToUserData(_data);
return tempObj;
}
#endregion
#region Helper Methods
// !! important
public static UserData JSONToUserData(string path) =>
JsonUtility.FromJson<UserData>(path);// JSON to Obj
public static string UserDataToJSON(UserData obj) => JsonUtility.ToJson(obj);//
Obj to JSON
// Making Directory if not present
private static void CheckDirectory(){
if (!Directory.Exists(FILE_PATH)){
Directory.CreateDirectory(FILE_PATH);
}
}
// Reset Data If User Play 1st Time
private static void CheckFilesPreviousData(){
// Checking File is not Null
UserData tempObj = LoadUnLockLevelData();
if(tempObj == null){
const int FIRSTLEVEL = 1;
SaveUnLockedLevelData(FIRSTLEVEL);
Debug.Log("Donee");
}
}
#endregion
}

C# how to automatically call a void or create an object when making a new class

In my test scenario, I basically have two classes Program.CS and SeleniumLibrary.cs
In program.cs I want to make a new class of SeleniumLibrary.cs, but what I want to accomplish is when I do new() I want to make a new instance of my ieDriver automatically.
class Program
{
static void Main(string[] args)
{
//make SeleniumLibrary._iedriver here somehow
SeleniumLibrary.SeleniumLibrary sl = new SeleniumLibrary.SeleniumLibrary();
sl.Navigate("www.google.com");
sl.Navigate("www.nfl.com");
}
}
class SeleniumLibrary
{
private InternetExplorerDriver _ieDriver { get; set; }
private InternetExplorerDriver ieDriver
{
get
{
if (_ieDriver == null)
_ieDriver = new InternetExplorerDriver();
return _ieDriver;
}
}
public void Navigate(string url)
{
ieDriver.Navigate().GoToUrl(url);
}
}
you can see inside of my navigate method I call ieDriver, but is there a way of cleaning up the code above?
I must be misunderstanding something here because whats wrong with:
class SeleniumLibrary
{
private readonly InternetExplorerDriver _ieDriver;
public SeleniumLibrary() //Constructor
{
_ieDriver = new InternetExplorerDriver();
}
public void Navigate(string url)
{
_ieDriver.Navigate().GoToUrl(url);
}
}
This is what DUD is proposing in his answer, I'm just spelling it out.
You can create an c-tor and inside it create the ieDrive

Access WPF Name properties in static method

I have a WPF application. In one of the XAML I have used Name attribute like as follows
x:Name="switchcontrol"
I have to access the control/property in .cs file using this.switchcontrol
My question is, I need to access the control in static method like
public static getControl()
{
var control = this.switchcontrol;//some thing like that
}
How to achieve this?
this is not accessible in static method. You can try save reference to your instance in static property, for example:
public class MyWindow : Window
{
public static MyWindow Instance { get; private set;}
public MyWindow()
{
InitializeComponent();
// save value
Instance = this;
}
public static getControl()
{
// use value
if (Instance != null)
var control = Instance.switchcontrol;
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
Instance = null; // remove reference, so GC could collect it, but you need to be sure there is only one instance!!
}
}
Some alternatives to Tony's method - you could pass in the window (or whatever xaml construct you are using) as a reference to the method, e.g.
public static void GetControl(MainWindow window)
{
var Control = window.switchcontrol;
}
if you are going to be passing several different derived types of Window, you could also do this:
public static void GetControl(Window window)
{
dynamic SomeTypeOfWindow = window;
try
{
var Control = SomeTypeOfWindow.switchcontrol;
}
catch (RuntimeBinderException)
{
// Control Not Found
}
}

Static functions have different static class variables?

This is a followup to a previous question: C# Static event null from within class
I have a class like this:
public class PlaylistModel {
public static event EventHandler PlaylistLoadError;
public static int myInt;
public static void LoadPlaylist()
{
try
{
// do some stuff, simulate exception
throw new InvalidOperationException();
}
catch(InvalidOperationException ex)
{
EventHandler handler = PlaylistLoadError;
if(handler != null)
{
PlaylistLoadError(null, null);
}
}
}
}
Else where in the program, I am setting the PlaylistLoadError EventHandler, like so:
public class MainPage {
public MainPage() {
PlaylistModel.PlaylistLoadError += MyErrorHandler;
PlaylistModel.myInt = 5;
}
public static void MyErrorHandler(object sender, EventArgs e)
{
Debug.WriteLine("There was an error");
}
}
Now, inside of LoadPlaylist, PlaylistLoadError is null and myInt is 0, despite setting them elsewhere. Later, when I create an instance of PlaylistModel, PlaylistLoadError and myInt are the correct values. So my question is this - do static functions of a class somehow access different versions of static class variables? I have checked the memory addresses of the static variables, and they are indeed different depending on if I'm inside of a non-static vs. a static function.
Static variables are static and will remain the same while the program is running unless something is called to change it.
If you want to find out what is happening I would change the field to:
private static int _myInt;
and then add:
public static int myInt
{
get { return _myInt; }
set { _myInt = value; }
}
and then add a break point at on set so you can find out when it is being changed.

Categories

Resources