Is there a way to get rid of practise.AcademicProgram in the output when the display() is called for an object initialized by the parameterized constructor. In my code below this occurs when s2.Display(); is executed.
Below is my working code for the same:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace practise
{
public class AcademicProgram
{
//Memnber variables
private int programCode;
private string programName;
private int programCredits;
//Properties for reading and writting the values of private fields
public int ProgramCode { get => programCode; set => programCode = value; }
public string ProgramName { get => programName; set => programName = value; }
public int ProgramCredits { get => programCredits; set => programCredits = value; }
//Default Constructor
public AcademicProgram()
{
}
//Parameterized Constructor
public AcademicProgram (int programCode, string programName, int programCredits)
{
this.programCode = programCode;
this.programName = programName;
this.programCredits = programCredits;
}
public void DisplayResults()
{
Console.WriteLine("Program Code: {0}\nProgram Name: {1}\nProgram Credits: {2}\n", programCode, programName, programCredits);
Console.WriteLine();
}
}
public class Instructor
{
//Member variables
public string forename;
public string surname;
public int identificationNumber;
public AcademicProgram academicProgram;
//Default Constructor
public Instructor()
{
this.forename = string.Empty;
this.surname = string.Empty;
this.identificationNumber = 0;
this.academicProgram = null;
}
//Parameterized Constructor
public Instructor(string forename, string surname, int identificationNumber, AcademicProgram academicProgram)
{
this.forename = forename;
this.surname = surname;
this.identificationNumber = identificationNumber;
this.academicProgram = academicProgram;
}
// Member Function to display values of member variables on Console.
public void Display()
{
Console.WriteLine(this.forename + ", " + this.surname + ", " + this.identificationNumber + ", " + this.academicProgram);
Console.WriteLine();
}
//Driver function
static void Main(string[] args)
{
//Instantiating object to call non-static member method
Instructor p = new Instructor();
p.Go();
Console.ReadKey();
}
//Non-static Member function
public void Go()
{
//Instantiating object without passing any values on runtime.
Instructor s = new Instructor();
//Instantiating object of AcademicProgram class without passing any values on runtime.
AcademicProgram progName = new AcademicProgram ();
//Set the values of fields using properties
progName.ProgramCode = 8230;
progName.ProgramName = "Systems Development: Cocnepts and Analysis";
progName.ProgramCredits = 4;
// Instantiating object while providing values on runtime.
Instructor s2 = new Instructor("Eddie ", "Jessup", 2394589, progName);
//Call to display method
s.Display();
s2.Display();
progName.DisplayResults();
}
}
}
Which gives an output shown here
Aside from override ToString(), I was able to fix it by a simple fix in display() of Instructor class as below:
public void Display()
{
Console.WriteLine(this.forename + ", " + this.surname + ", " + this.identificationNumber + ", " + this.academicProgram.ProgramCode + ", " + this.academicProgram.ProgramName + ", " + this.academicProgram.ProgramCredits);
Console.WriteLine();
}
Related
I'm making a quiz game and I'm stuck at this problem that is probably easy to do.
I have this script, which gets JSON data from server and separates it:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System;
using TMPro;
[Serializable]
public class RootObject
{
public Results[] Result;
}
[Serializable]
public class Results
{
public string id;
public string question;
public string answer1;
public string answer2;
public string answer3;
public string answer4c;
}
public class DataLoader : MonoBehaviour
{
public PickPlace pickplace;
public string URLBase;
public void GetQustion()
{
URLBase = pickplace.url;
StartCoroutine(Run());
}
IEnumerator Run()
{
var req = CreateReturnPlayerDataRequest();
yield return req.SendWebRequest();
var results = HandleReturnPlayerDataRequest(req);
// Izvada konsolē saņemtos datus
Debug.Log("Quesiton: " + results.Result[0].question + " Answer1: " + results.Result[0].answer1 + " Answer2: " + results.Result[0].answer2 + " Answer3: " + results.Result[0].answer3 + " Answer4: " + results.Result[0].answer4c);
}
public UnityWebRequest CreateReturnPlayerDataRequest()
{
var req = UnityWebRequest.Get(URLBase);
return req;
}
public static RootObject HandleReturnPlayerDataRequest(UnityWebRequest req)
{
if (req.isNetworkError)
{
Debug.LogError("Failed to POST /player/register");
return new RootObject();
}
var results = JsonUtility.FromJson<RootObject>("{\"Result\":" + req.downloadHandler.text + "}");
return results;
}
}
My question is:
How can I call out array in, for example my GameManager script and call out separated data, so that I can put for example question text from JSON data into Text object and all 4 answers to buttons?
Currently you have a method to start the request but you never wait until / will know when it is done!
I would simply use an Action<RootObject> as parameter so you can add a callback listener and react to the result when it is invoked.
public class DataLoader : MonoBehaviour
{
public PickPlace pickplace;
public string URLBase;
public void GetQuestions(Action<RootObject> onSuccess)
{
URLBase = pickplace.url;
StartCoroutine(Run(onSuccess));
}
IEnumerator Run(Action<RootObject> onSuccess)
{
var req = CreateReturnPlayerDataRequest();
yield return req.SendWebRequest();
var results = HandleReturnPlayerDataRequest(req);
if(results == null)
{
yield break;
}
Debug.Log("Quesiton: " + results.Result[0].question + " Answer1: " + results.Result[0].answer1 + " Answer2: " + results.Result[0].answer2 + " Answer3: " + results.Result[0].answer3 + " Answer4: " + results.Result[0].answer4c);
// Now invoke the Callback so whoever started the post call gets the results
onSuccess?.Invoke(results);
}
public UnityWebRequest CreateReturnPlayerDataRequest()
{
var req = UnityWebRequest.Get(URLBase);
return req;
}
private RootObject HandleReturnPlayerDataRequest(UnityWebRequest req)
{
if(req.isHttpError || req.isNetworkError)
{
Debug.LogError($"Failed to POST /player/register! Failed with {req.responseCode} - Reason: {req.error}");
onDone?.Invoke(null);
return null;
}
var results = JsonUtility.FromJson<RootObject>("{\"Result\":" + req.downloadHandler.text + "}");
return results;
}
}
So now you can call it from another class like e.g.
// Drag these in via the Inspector
[SerializeField] private DataLoader dataLoader;
[Space]
[SerializeField] private Text questionText;
[Space]
[SerializeField] private Text button1Text;
[SerializeField] private Text button2Text;
[SerializeField] private Text button3Text;
[SerializeField] private Text button3Text;
public void SomeMethod()
{
// Do the post call and react once the results are there either as lambda expression
dataLoader.GetQuestions(results => {
Debug.Log("Successfully received data. Will update GUI", this);
// do something with the results now e.g.
var first = results.Result[0];
questionText.text = first.question;
button1Text.text = first.answer1;
button2Text.text = first.answer2;
button3Text.text = first.answer3;
button4Text.text = first.answer4;
});
// alternatively you can do the same also using a method
dataLoader.GetQuestions(OnPostRequestFinished);
}
private void OnPostRequestFinished(RootObject results)
{
Debug.Log("Successfully received data. Will update GUI", this);
// do something with the results now e.g.
var first = results.Result[0];
questionText.text = first.question;
button1Text.text = first.answer1;
button2Text.text = first.answer2;
button3Text.text = first.answer3;
button4Text.text = first.answer4;
}
I have a problem, where Json data is taken from server and then called out, but always outputs NULL. You can test code if you want to, Url is public.
This is Json data that I get from server
[{"id":"3","question":"Cik ir 4 + 4 = ?","answer1":"3","answer2":"13","answer3":"7","answer4c":"8"}]
How do I fix this, so Json data outputs correctly?
Thank you.
using System.Collections;
using System.Collections.Generic;
using System.Net.Mime;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System;
public class Code : MonoBehaviour
{
public Text first;
public const string URLBase = "http://91.200.67.104:8080/test/json.php";
[System.Serializable]
public class Results
{
public string id;
public string question;
public string answer1;
public string answer2;
public string answer3;
public string answer4c;
}
void Start()
{
StartCoroutine(Run());
}
IEnumerator Run()
{
var req = CreateReturnPlayerDataRequest();
yield return req.SendWebRequest();
var results = HandleReturnPlayerDataRequest(req);
first.text = results.id + " dasdasdas " + results.question;
}
public static UnityWebRequest CreateReturnPlayerDataRequest()
{
var req = UnityWebRequest.Get(URLBase);
return req;
}
public static Results HandleReturnPlayerDataRequest(UnityWebRequest req)
{
if (req.isNetworkError)
{
Debug.LogError("Failed to POST /player/register");
return new Results();
}
// Debug izvada datus console
Debug.Log("{\"Results\":" + req.downloadHandler.text + "}");
Results results = JsonUtility.FromJson<Results>("{\"Results\":" + req.downloadHandler.text + "}");
Debug.Log("ID:" + results.id + " ;question: " + results.question + " ; " + results.answer1);
Debug.Log(results.id);
Debug.Log(results.question);
Debug.Log(results.answer1);
return results;
}
}
Your deserialization class structure is incorrect.
Firstly, the json data you are receiving from the server is an array/collection (it is surrounded by square brackets "[ ]").
Secondly, you are placing it in the "Results" field of a parent object.
Therefore, this would be the correct structure:
[System.Serializable]
public class RootObject
{
public List<Results> Results;
}
[System.Serializable]
public class Results
{
public string id;
public string question;
public string answer1;
public string answer2;
public string answer3;
public string answer4c;
}
Usage:
var obj = JsonUtility.FromJson<RootObject>("{\"Results\":" + req.downloadHandler.text + "}");
Results serverData = obj.Results[0];
Small brief of what i need and what i currently have
I connect to a database and get my data from it and i get ( Name , LongNumber) and basically i have an event (action) that fires when the event occurs (this action gives me a LongNumber aswell).
I need to compare the LongNumbers between the one i got from the event (action) and the one from my database, and if they are similar i take the name and use it.
for example Hello, Alex ( alex is taken from the database)
Issue
I get Index out of range, and using my logic all texts will change what i'm trying to achieve is to change the text to the name of the person that got the Long number the same as the longNumber from the event
Code: Gettings Data from the database
using UnityEngine;
using System.Collections;
using MySql.Data.MySqlClient;
using System;
using System.Linq;
using System.Collections.Generic;
public class MySqlTestScript : MonoBehaviour
{
private static MySqlTestScript _instnace;
public static MySqlTestScript sharedInstance()
{
return _instnace;
}
string row = "";
public string host = "*****";
public string database = "*******";
public string usrename= "*******";
public string password = "******";
public List<Data> userData = new List<Data>();
Data data;
void Awake()
{
_instnace = this;
}
// Use this for initialization
public void Start()
{
GetDataFromDatabase();
}
public string GetDataFromDatabase()
{
string myConnectionString = "Server="+host+";Database="+database+";Uid="+usrename+ ";Pwd="+password+";";
MySqlConnection connection = new MySqlConnection(myConnectionString);
MySqlCommand command = connection.CreateCommand();
command.CommandText = "SELECT * FROM Users";
MySqlDataReader Reader;
try
{
connection.Open();
Reader = command.ExecuteReader();
while (Reader.Read())
{
for (int i = 0; i < Reader.FieldCount; i++)
{
//rfid_tags.Add (Reader.GetString("UserName"));
//rfid_tags.Add(Reader.GetString("RFID_Tag"));
data = new Data(Reader.GetString("UserName"), Reader.GetString("RFID_Tag"));
userData.Add(data);
// ws.DomainUrl = reader.GetString("DomainUrl");
// rfid_tags.Add(Reader.GetValue(i).ToString() + ",");
// row += Reader.GetValue(i).ToString() + ", ";
}
Debug.Log(row);
}
}
catch (Exception x)
{
Debug.Log(x.Message);
return x.Message;
}
connection.Close();
return row;
}
}
public class Data {
public string username { get; set; }
public string rfid { get; set; }
public Data(string _name, string _rfid)
{
username = _name;
rfid = _rfid;
}
public void SetUserName(string _userName) { username = _userName; }
public void SetRFID(string _rfid) { rfid = _rfid; }
}
Code for Comparing the values from the event(action) and showing the text
void OnTagsReported(ImpinjReader sender, TagReport report)
{
Debug.Log("OnTagsReported");
// This event handler is called asynchronously
// when tag reports are available.
// Loop through each tag in the report
// and print the data.
foreach (Tag tag in report)
{
Debug.Log(tag.Epc);
// Debug.Log(MySqlTestScript.sharedInstance().rfid_tags[0]);
Debug.Log("STEP ONE");
for (int i = 0; i < MySqlTestScript.sharedInstance().userData.Count; i++)
{
Debug.Log("STEP TWO");
if (tag.Epc.ToString().Trim() == MySqlTestScript.sharedInstance().userData[i].rfid)
{
Debug.Log("STEP THREE");
// TODO References the Name
Loom.QueueOnMainThread(() => {
namesTxt[i].text = MySqlTestScript.sharedInstance().userData[i].username;
});
}
}
As you can see in the Event script it's so unflexible and it gives index out of range if my database has less than 6 rows. I need to make it more friendly and generic
Any help would be appreciated and i hope my question is clear Thank you :)!
This should make more sense:
Database:
using UnityEngine;
using System.Collections;
using MySql.Data.MySqlClient;
using System;
using System.Linq;
using System.Collections.Generic;
public class MySqlTestScript : MonoBehaviour
{
private static MySqlTestScript _instnace;
public static MySqlTestScript sharedInstance()
{
return _instnace;
}
string row = "";
public string host = "*****";
public string database = "*******";
public string usrename= "*******";
public string password = "******";
public List<AppUser> users = new List<AppUser>();
void Awake()
{
_instnace = this;
}
// Use this for initialization
public void Start()
{
GetDataFromDatabase();
}
public string GetDataFromDatabase()
{
string myConnectionString = "Server=" + host + ";Database=" + database + ";Uid=" + usrename + ";Pwd=" + password + ";";
MySqlConnection connection = new MySqlConnection(myConnectionString);
MySqlCommand command = connection.CreateCommand();
command.CommandText = "SELECT * FROM users";
MySqlDataReader Reader;
try
{
connection.Open();
Reader = command.ExecuteReader();
while (Reader.Read())
{
users.Add(new AppUser() {
username = Reader.GetString("UserName").Trim(),
rfid = Reader.GetString("longNumbers ").Trim()
});
}
}
catch (Exception x)
{
Debug.Log(x.Message);
return x.Message;
}
connection.Close();
return row;
}
}
Data object:
public Class AppUser
{
public string rfid { get; set; }
public string username { get; set; }
}
Event/data comparison:
void OnTagsReported(ImpinjReader sender, TagReport report)
{
Debug.Log("OnTagsReported");
// This event handler is called asynchronously
// when tag reports are available.
// Loop through each tag in the report
// and print the data.
foreach (Tag tag in report)
{
Debug.Log(tag.Epc);
List<AppUser> appUsers = MySqlTestScript.sharedInstance().users;
int numUsers = appUsers.Count;
Debug.Log(numUsers);
for (int i = 0; i < numUsers; i++)
{
if (tag.Epc.ToString().Trim() == appUsers[i].rfid)
{
// TODO References the Name
Loom.QueueOnMainThread(() => {
if (i < namesTxt.Count) namesTxt[i].Text = appUsers[i].username; //assumes textnames is a "List" of textboxes and is already populated with instances of text1, text2 text3 etc. The if is just to guard against there being more rows in the DB than textboxes
});
}
}
}
}
One way to get around this is to wrap each of your cases in another if statement to check if the database has that many rows
if (MySqlTestScript.sharedInstance().longNumbers.Length > 1) {
if (tag.Epc.ToString().Trim() == MySqlTestScript.sharedInstance().longNumbers[0].ToString()) {
if(MySqlTestScript.sharedInstance().userNames[0] != null)
txt1.text = "Hello "+ MySqlTestScript.sharedInstance().userNames[0];
}
}
}
else {
txt1.text = "";
}
This will avoid your index out of range exception. In each wrapping case you will need to increment the comparison to be 1, 2, 3, etc.
It is not the prettiest solution but will avoid the exception. Another option would be to wrap in a try-catch block. Again not the prettiest but would accomplish the task.
I'd sincerely appreciate if you looked through some of my code as I can't seem to be able to fix it myself, and this will also hopefully help others understand serialization better.
I have four pieces of related code here, with anything seemingly irrelevant cut out. I'm trying to create a user profile in a set up where the user then chooses from a range of games to play. Only options/settings for the chosen games, in this case something to do with a fish, are saved.
The error in the title occurs in the 4th section [feel free to skip to that] which is the OptionsController.LoadOptions() function at
FishData.Store data = (FishData.Store)bf.Deserialize(fileOpt);
I have this at the top of all following sections:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
1) Profile data structure:
public class Profile { //Profile variables
public static string id;
public static string name;
public static string dob;
public static bool fishEnabled;
public static bool birdEnabled;
public static string stringTest;
[System.Serializable]
public class Store { //Profile variables
public string id;
public string name;
public string dob;
public bool fishEnabled;
public bool birdEnabled;
public string stringTest;
}
}
2) Fish data structure:
public class FishData { //static Fish variables to be used in game
public static bool sizeInc;
public static bool speedInc;
public static int level;
public static bool toxic;
public static bool handLeft;
public static bool timer;
public static int timerVal;
public static int percentReq;
public static int successReq;
public static string testStringTwo;
public static List<StatController.Session> sessions = new List<StatController.Session>();
[System.Serializable]
public class Store { //non static variable set for serialization
public bool sizeInc;
public bool speedInc;
public int level;
public bool toxic;
public bool handLeft;
public bool timer;
public int timerVal;
public int percentReq;
public int successReq;
public string testStringTwo;
public List<StatController.Session> sessions = new List<StatController.Session>();
}
}
3) The script where the data file was initially created and where there didn't seem to be problems:
public class ProfileController : MonoBehaviour {
public static string currentID;
//create ----
public InputField idField;
public InputField nameField;
public InputField dobField;
public Toggle fishToggle;
public Toggle birdToggle;
//open ------
public Button idTitleButton;
public Text nameText;
public Text dobText;
public Text testText;
public InputField numField;
void Save() { //saves new ID and declares required variables based on game choice
Debug.Log("id =" + idField.text + ", name = " + nameField.text + ", save");
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath + "/" + idField.text + ".dat");
Profile.Store data = new Profile.Store(); //sets Profile variables
currentID = idField.text;
data.id = idField.text;
data.name = nameField.text;
data.dob = dobField.text;
data.fishEnabled = fishToggle.isOn;
data.birdEnabled = birdToggle.isOn;
Profile.id = idField.text;
Profile.name = nameField.text;
Profile.dob = dobField.text;
Profile.fishEnabled = fishToggle.isOn;
Profile.birdEnabled = birdToggle.isOn;
bf.Serialize(file, data); //saves Profile variables
if (fishToggle.isOn) {
FishData.Store dataFish = new FishData.Store(); //sets default Fish variables
dataFish.sizeInc = false;
dataFish.speedInc = false;
dataFish.level = 5;
dataFish.toxic = true;
dataFish.handLeft = false;
dataFish.timer = false;
dataFish.timerVal = 240;
dataFish.percentReq = 0;
dataFish.successReq = 0;
bf.Serialize(file, dataFish); //saves default Fish variables
Debug.Log("level = " + dataFish.level);
}
file.Close(); //closes save file
idSelectField.text = idField.text; //ensures current ID is used as selected ID where needed
EnableOpenProfile(); //loads new profile
}
void Load() {
if (File.Exists(Application.persistentDataPath + "/" + idField.text + ".dat")) { //loads save file
currentID = idField.text;
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/" + idField.text + ".dat", FileMode.Open);
Profile.Store data = (Profile.Store)bf.Deserialize(file);
nameField.text = data.name; //loads saved Profile details and settings
fishToggle.isOn = data.fishEnabled;
birdToggle.isOn = data.birdEnabled;
fishPlayButton.enabled = data.fishEnabled;
birdPlayButton.enabled = data.birdEnabled;
FishData.Store dataFish = (FishData.Store)bf.Deserialize(file); //loads saved Fish settings
FishData.sizeInc = dataFish.sizeInc;
FishData.speedInc = dataFish.speedInc;
FishData.toxic = dataFish.toxic;
FishData.timer = dataFish.timer;
FishData.level = dataFish.level;
FishData.timerVal = dataFish.timerVal;
FishData.percentReq = dataFish.percentReq;
FishData.successReq = dataFish.successReq;
FishData.handLeft = dataFish.handLeft;
file.Close(); //closes save file
nameText.text = "Name : " + data.name + " ID : " + data.id; //displays profile details
dobText.text = "DOB : " + data.dob;
}
else return;
}
}
4) The main script that produces the error when trying to load what was saved in the previous script:
public class OptionsController : MonoBehaviour {
public static bool handLeft = false;
public Toggle sizeIncToggle;
public Toggle speedIncToggle;
public Toggle toxicToggle;
public Toggle timerToggle;
public Toggle leftToggle;
public Toggle rightToggle;
public InputField levelField;
public InputField timerValField;
public InputField percentReqField;
public InputField successReqField;
void LoadOptions() {
if (File.Exists(Application.persistentDataPath + "/" + ProfileController.currentID + ".dat")) {
BinaryFormatter bf = new BinaryFormatter();
FileStream fileOpt = File.Open(Application.persistentDataPath + "/" + ProfileController.currentID + ".dat", FileMode.Open);
FishData.Store data = (FishData.Store)bf.Deserialize(fileOpt); //[[ERROR HERE]]
sizeIncToggle.isOn = data.sizeInc;
speedIncToggle.isOn = data.speedInc;
toxicToggle.isOn = data.toxic;
timerToggle.isOn = data.timer;
levelField.text = data.level.ToString();
timerValField.text = data.timerVal.ToString();
percentReqField.text = data.percentReq.ToString();
successReqField.text = data.successReq.ToString();
fileOpt.Close();
}
}
public void SaveOptions() {
Debug.Log("name = " + ProfileController.currentID + ", save");
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath + "/" + ProfileController.currentID + ".dat");
FishData.Store data = new FishData.Store();
data.sizeInc = FishData.sizeInc;
data.speedInc = FishData.speedInc;
data.toxic = FishData.toxic;
data.timer = FishData.timer;
data.level = FishData.level;
data.timerVal = FishData.timerVal;
data.percentReq = FishData.percentReq;
data.successReq = FishData.successReq;
data.handLeft = FishData.handLeft;
bf.Serialize(file, data);
Debug.Log("level = " + FishData.level);
file.Close();
}
}
Thank you.
To ensure you are serializing/deserializing in the correct order it is best that you create a "holding" class which contains both a Fish.Store variable and Profile.Store variable. If you serialize and deserilize in different orders you will run into issues like trying to deserialize a Fish.Store object to Profile.Store.
Try creating another class with public variables of Fish.Store and Profile.Store, like:
public class ExampleClass
{
public Fish.Store FishStore;
public Profile.Store ProfileStore;
public ExampleClass()
{
}
}
Then do:
ExampleClass example = new ExampleClass();
example.ProfileStore = data;
example.FishStore = dataFish;
//File Create stuff, etc
bf.Serialize(file, example);
//File close stuff, etc
And to deserialize:
ExampleClass e = (ExampleClass)bf.Deserialize(fileOpt);
data = e.ProfileStore;
dataFish = e.FishStore;
If you only wish to serialize/deserialize one class at a time, it is best practice to read/write to/from one file per serialized class.
Correct me if I'm wrong but it seems you first save Profile.Store
and then you save FishData.Store.
Then on the load you try to retreive the FishData.Store when the Profile.Store is first in the file.
(I'm assuming you use the load from script 4 and the save in script 3.)
Easiest way that I can add a title row to each of these files. I can't put it in the Log()'s because it would add the title row each time I reference the test.Log()'s
I thought about referencing 3 new int fields and each time I reference a Log1/2/3() it checks the value of the int and if it's 1 then add the title column else don't.I did one below but it seems redundant I figured there must be a better way.
public class Test
{
public static string File1 = DateTime.Now.ToString("yyyy-MM-dd") + "test1.csv";
public static int a = 0;
public static string File2 = DateTime.Now.ToString("yyyy-MM-dd") + "test2.csv";
public static string File3 = DateTime.Now.ToString("yyyy-MM-dd") + "test3.csv";
private static object _lockObj = new Object();
public static void Log1(string error, string record)
{ a++;
if(a==1){
lock (_lockObj)
{
File.AppendAllText(test.File1, "ERROR" + Environment.NewLine)
File.AppendAllText(test.File1, error + "," + record + Environment.NewLine);
}
}
else{
File.AppendAllText(test.File1, error + "," + record + Environment.NewLine);
}
}
public static void Log2(string message)
{
lock (_lockObj)
{
File.AppendAllText(test.File2, message + Environment.NewLine);
}
}
public static void Log3(Test c)
{
lock (_lockObj)
{
File.AppendAllText(test.File3, c + Environment.NewLine);
}
}
}
You may create a class like this:-
public class HeaderOnceAppender : RollingFileAppender
{
protected override void WriteHeader()
{
if (LockingModel.AcquireLock().Length == 0)
{
base.WriteHeader();
}
}
If you want put a Title row at the top of the file when creating it...
if(!System.IO.File.Exists(test.File1)) //if the file doesn't exist
{ //insert your header at the top
File.AppendAllText(test.File1,"My Header Line")
}
This will only append once when the file is first created