My goal is to change the value of a field after it is read. And I think it is possible running the "AfterRead" event.
My current version of the library is 2.0.0.
I have tested the next getting an error:
public class sealed MyClass: INotifyRead
{
// ...
public void AfterRead(EngineBase engine, AfterReadEventArgs e)
{
}
}
The error message is:
Cannot find the namespace "AfterReadEventArgs". Missing the "using" directive or assembly reference.
I have read the next code in the docs:
FileHelperEngine engine = new FileHelperEngine(typeof(Orders));
engine.BeforeReadRecord += new BeforeReadRecordHandler(BeforeEvent);
Orders[] res = engine.ReadFile("report.txt") as Orders[];
I don't know if it is needed to declare the delegate in the source code or it is enough the declaration of the event in the Mapping Class.
Thanks a lot!
The signature of the AfterRead event is different in 2.0.0.0. Here's a working example.
using System;
using System.Diagnostics;
using FileHelpers;
namespace ConsoleApp
{
[DelimitedRecord(";")]
public sealed class MyClass : INotifyRead
{
public string Field1;
public string Field2;
public void AfterRead(EngineBase engine, string line)
{
Field1 = "ModifiedValue1";
}
}
internal class Program
{
static void Main(string[] args)
{
FileHelperEngine engine = new FileHelperEngine(typeof(MyClass));
var records = engine.ReadString("Value1;Value2");
var firstRecord = records[0] as MyClass;
Debug.Assert(firstRecord.Field1 == "ModifiedValue1");
Console.Write("All OK. Field1 had the modified value.");
Console.ReadKey();
}
}
}
so I want to make it easy to call Console.WriteLine() (from the namespace system) so I wrote:
using System;
namespace main
{
namespace easier
{
public class print
{
public print(string input)
{
Console.WriteLine(input);
}
}
}
}
But when I try to call print("Hello World); it says CS1955: Non-invocable member 'print' cannot be used like a method.
Is there a way so I don't have to do class.print("Hello World"); just print("Hello World");?
Thanks in advance!
You can use using static
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-static
using System;
using static Easier;
class Program
{
static void Main(string[] args)
{
Print("message");
}
}
public static class Easier
{
public static void Print(string value)
{
Console.WriteLine(value);
}
}
How can I start an Activity from a non-Activity in Xamarin.Forms?
In the main startup project, MyApp.Droid, I have MyActivity.cs.
In the PCL project, MyApp.Plugin.Android, I have a non-activity class, MyClass.cs.
In MyClass.cs I need to run some code in MyActivity.cs.
How can I do that?
Thanks.
MyActivity.cs:
public void MyMethod()
{
// [Working Code...]
}
MyClass.cs:
public void OnSuccess
{
// What should I put here to call MyMethod?
}
something like this should do the trick! (I think, it been a while...)
MyClass.cs:
using System;
namespace MyClass {
public static class Program {
public static void MyMethod()
{
// [Working Code...]
}
}
}
MyActivity.cs:
using System;
using MyClass; //get your other file by the namespace
namespace MyActivity {
public static class Program {
public static void OnSuccess()
{
Program.MyMethod(); //[class name]..MyMethod();
}
}
}
I have void Start() with string snapshotJson declared inside of it, and I have private void LoadGameData() that needs to call the value of snapshotJson. Declaring snapshotJson public doesn't work, I assume because of void. From what I read I should be using getters and setters, but I have no idea how they work and every guide I've read explaining it makes it seem very simple, but they explain it so simply I don't understand how exactly I'm supposed to use it, or how I can call the value after using the get/set functions.
Could anyone explain how I can get the variable from one class to another? In my code, LoadGameData isn't able to call the value of snapshotJson, I'm not sure what I'm missing.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.IO;
using Firebase;
using Firebase.Unity.Editor;
using Firebase.Database;
using System;
public class DataController : MonoBehaviour
{
private RoundData[] allRoundData;
private PlayerProgress playerProgress;
[Serializable]
public class FirebaseStart : MonoBehaviour
{
public string snapshotJson { get; set; }
void Start()
{
// Set up the Editor before calling into the realtime database.
FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("https://FIREBASEDATABASE");
// Get the root reference location of the database.
DatabaseReference reference =
FirebaseDatabase.DefaultInstance.RootReference;
FirebaseDatabase.DefaultInstance
.GetReference("allRoundData")
.GetValueAsync().ContinueWith(task => {
if (task.IsFaulted)
{
// Handle the error...
}
else if (task.IsCompleted)
{
// DataSnapshot snapshot = task.Result;
snapshotJson = JsonUtility.ToJson(task.Result);
}
});
}
}
// Use this for initialization
void Start ()
{
DontDestroyOnLoad(gameObject);
LoadGameData();
LoadPlayerProgress();
SceneManager.LoadScene("MenuScreen");
}
public RoundData GetCurrentRoundData()
{
return allRoundData [0];
}
public void SubmitNewPlayerScore(int newScore)
{
if (newScore > playerProgress.highestScore)
{
playerProgress.highestScore = newScore;
SavePlayerProgress();
}
}
public int GetHighestPlayerScore()
{
return playerProgress.highestScore;
}
// Update is called once per frame
void Update () {
}
private void LoadPlayerProgress()
{
playerProgress = new PlayerProgress();
if (PlayerPrefs.HasKey("highestScore"))
{
playerProgress.highestScore = PlayerPrefs.GetInt("highestScore");
}
}
private void SavePlayerProgress()
{
PlayerPrefs.SetInt("highestScore", playerProgress.highestScore);
}
public void LoadGameData()
{
GameData loadedData = JsonUtility.FromJson<GameData>(snapshotJson);
Console.WriteLine(snapshotJson);
allRoundData = loadedData.allRoundData;
}
The LoadGameData() method cannot access it from the Main() method because it is local to that function scope. However, you can pass the value from the Main() method to the LoadGameData() using the code below:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
private static void LoadGameData(String input) {
// Do something inside your input here.
}
public static void Main() {
Start();
}
public static void Start()
{
string snapshotJson = "Sample data";
// Same Class Call
LoadGameData(snapshotJson);
// Other Class Call
var otherClassInstance = new TestClass();
otherClassInstance.LoadGameData(snapshotJson);
}
}
public class TestClass {
public void LoadGameData(String input) {
// Do something inside your input here.
}
}
Assuming you refer to methods instead of classes (or rather: sharing data between objects), this is what you could do. Here's an example of a dedicated class for your Game objects, with SnaphopJson being a public property that can be accessed and changed from any other object. Changing the setter to private would ensure only it can only be read from anything but objects of this class.
public class Game
{
public string SnapshotJson { get; set; }
private void LoadGameData()
{
// load the json, e.g. by deserialization
SnapshotJson = "{}";
}
public void Start()
{
// access the content of your snapshot
var s = SnapshotJson;
}
}
If the variable snapshotJson is declared inside the body of the Start method, it will only be accessible within that method. If you want the variable to be accessible in other methods of your class, you may want to declare it as a member variable. This is how it looks like. You would need to declare it as a public property only if you need to access the value of snapshotJson outside of your class instance.
public class MyClass
{
string snapshotJson;
private void Start()
{
// Assign value to snapshotJson here
snapshotJson = "foo";
}
private void LoadGameData
{
// Use value of snapshotJson here
string s = snapshotJson;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Taking data from Main Thread\n->");
string message = Console.ReadLine();
ThreadStart newThread = new ThreadStart(delegate { Write(message); });
Thread myThread = new Thread(newThread);
}
public static void Write(string msg)
{
Console.WriteLine(msg);
Console.Read();
}
}
}
You can also use a the CallContext if you have some data that you want to "flow" some data with your call sequence. Here is a good blog posting about LogicalCallContext from Jeff Richter.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Taking data from Main Thread\n->");
string message = Console.ReadLine();
//Put something into the CallContext
CallContext.LogicalSetData("time", DateTime.Now);
ThreadStart newThread = new ThreadStart(delegate { Write(message); });
Thread myThread = new Thread(newThread);
}
public static void Write(string msg)
{
Console.WriteLine(msg);
//Get it back out of the CallContext
Console.WriteLine(CallContext.LogicalGetData("time"));
Console.Read();
}
}
}
There is an overload to Thread.Start that lets you pass in a parameter.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Taking data from Main Thread\n->");
string message = Console.ReadLine();
Thread myThread = new Thread(Write);
myThread.Start(message);
}
public static void Write(object obj)
{
string msg = (string)obj;
Console.WriteLine(msg);
Console.Read();
}
}
One way to get the same effect of passing a variable to a thread is to make a classwide private data member of the type you wish to pass to the thread. Set this value to whatever you want before you start the thread. If you have many threads, you will need to put a lock on this classwide data member to prevent unexpected values. Or you can use .NET native Mutex functionality to control access to the variable.
For example (didn't test this, just wrote it up on the fly):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
private string threadVariable;
static void Main(string[] args)
{
Console.WriteLine("Taking data from Main Thread\n->");
string message = Console.ReadLine();
threadVariable = "stuff";
Thread myThread = new Thread(Write);
Thread.IsBackground = true;
Thread.Start();
}
public static void Write()
{
Console.WriteLine(stuff);
Console.Read();
}
}
}
If you are asking how to pass parameters to threads, refer to this:
http://www.yoda.arachsys.com/csharp/threads/parameters.shtml
I am not sure if I understand your question correctly, but the following MSDN article shows how to pass data to a thread in the way that you are doing it (i.e., via ThreadStart and a delegate):
Passing data to thread
using System;
using System.Threading;
class Test
{
static void Main()
{
// To start a thread using a static thread procedure, use the
// class name and method name when you create the ThreadStart
// delegate. Beginning in version 2.0 of the .NET Framework,
// it is not necessary to create a delegate explicitly.
// Specify the name of the method in the Thread constructor,
// and the compiler selects the correct delegate. For example:
//
// Thread newThread = new Thread(Work.DoWork);
//
ThreadStart threadDelegate = new ThreadStart(Work.DoWork);
Thread newThread = new Thread(threadDelegate);
newThread.Start();
// To start a thread using an instance method for the thread
// procedure, use the instance variable and method name when
// you create the ThreadStart delegate. Beginning in version
// 2.0 of the .NET Framework, the explicit delegate is not
// required.
//
Work w = new Work();
w.Data = 42;
threadDelegate = new ThreadStart(w.DoMoreWork);
newThread = new Thread(threadDelegate);
newThread.Start();
}
}
class Work
{
public static void DoWork()
{
Console.WriteLine("Static thread procedure.");
}
public int Data;
public void DoMoreWork()
{
Console.WriteLine("Instance thread procedure. Data={0}", Data);
}
}
I use a separate worker class and populate a member variable in the constructor, I then use a void method as my delegate that uses the private member variable:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Taking data from Main Thread\n->");
string message = Console.ReadLine();
WorkerClass workerClass = new WorkerClass(message);
ThreadStart newThread = new ThreadStart(workerClass.DoWork);
Thread myThread = new Thread(newThread);
myThread.Start();
Console.Read();
}
}
internal class WorkerClass
{
private string _workerVariable = "";
internal WorkerClass(string workerVariable)
{
_workerVariable = workerVariable;
}
internal void DoWork()
{
Console.WriteLine(_workerVariable);
}
}
}
One handy set of classes I wrote up in vb2005 would allow the easy creation of a delegate with one to four bound arguments and zero or one unbound arguments. A huge mess of copy/paste code, since .net doesn't support variadic generics, but one could create a MethodInvoker which would call foo(bar,boz) by saying (vb.net syntax, but the approach would be the same in C#):
theMethodInvoker = InvMaker.NewInv(addressof foo, bar, boz)
theMethodInvoker() ' Calls foo(bar,boz)
which would generate an object containing fields Param1 as BarType, Param2 as BozType, and theAction as Action(of BarType, BozType). It would set those fields to bar, boz, and foo, and return a MethodInvoker which would call doIt, a method which called theAction(Param1, Param2). If I needed an Action(of Integer), I would use:
theMethodInvoker = ActionMaker(of Integer).NewInv(addressof foo, bar, boz)
theMethodInvoker(9) ' Calls foo(9,bar,boz)
Really slick. Lambdas avoid the need for a cut-and-paste library, but their internal implementation is similar. I've read that Lambdas cause difficulty with edit-and-continue; I know my method does not.