How can I write to a file from different class?
public class gen
{
public static string id;
public static string m_graph_file;
}
static void Main(string[] args)
{
gen.id = args[1];
gen.m_graph_file = #"msgrate_graph_" + gen.id + ".txt";
StreamWriter mgraph = new StreamWriter(gen.m_graph_file);
process();
}
public static void process()
{
<I need to write to mgraph here>
}
Pass the StreamWriter mgraph to your process() method
static void Main(string[] args)
{
// The id and m_graph_file fields are static.
// No need to instantiate an object
gen.id = args[1];
gen.m_graph_file = #"msgrate_graph_" + gen.id + ".txt";
StreamWriter mgraph = new StreamWriter(gen.m_graph_file);
process(mgraph);
}
public static void process(StreamWriter sw)
{
// use sw
}
However your code has some, difficult to understand, points:
You declare the class gen with two static vars. These vars are
shared between all instances of gen. If this is a desidered
objective, then no problem, but I am a bit puzzled.
You open the StreamWriter in your main method. This is not really
necessary given the static m_grph_file and complicates the cleanup in case your code raises
exceptions.
For example, in you gen class, (or in another class) you could write methods that work on the same file because the file name is static in the class gen
public static void process2()
{
using(StreamWriter sw = new StreamWriter(gen.m_graph_file))
{
// write your data .....
// flush
// no need to close/dispose inside a using statement.
}
}
You can pass a StreamWriter object as a parameter. Alternatively you could create a new instance inside your process method. I would also recommend wrapping your StreamWriter inside a using:
public static void process(StreamWriter swObj)
{
using (swObj)) {
// Your statements
}
}
Of course you could simply have your 'process' method like this:
public static void process()
{
// possible because of public class with static public members
using(StreamWriter mgraph = new StreamWriter(gen.m_graph_file))
{
// do your processing...
}
}
But from the design point of view this would make more sense (EDIT: full code):
public class Gen
{
// you could have private members here and these properties to wrap them
public string Id { get; set; }
public string GraphFile { get; set; }
}
public static void process(Gen gen)
{
// possible because of public class with static public members
using(StreamWriter mgraph = new StreamWriter(gen.GraphFile))
{
sw.WriteLine(gen.Id);
}
}
static void Main(string[] args)
{
Gen gen = new Gen();
gen.Id = args[1];
gen.GraphFile = #"msgrate_graph_" + gen.Id + ".txt";
process(gen);
}
Related
So simply put im trying to make a chat bot so I have chosen to make another class for my Stream writer so I've made a public class and then put a method etc. How would I mention that class in my main class in my main method?
static void Main(string[] args)
{
}
}
public class FileCreater2
{
public void Main2(string[] args)
{
StreamWriter File = new StreamWriter("Test_File.text");
File.Write("Hello world");
File.Close();
}
}
}
something like this:
public class Program
{
public static void Main(string[] args)
{
FileCreater2 fc2 = new FileCreater2();
fc2.Main2(null); //null passed just for demo
}
private class FileCreater2
{
public void Main2(string[] args)
{
StreamWriter File = new StreamWriter("Test_File.text");
File.Write("Hello world");
File.Close();
}
}
}
Cosidering I can't change class ReadTheFile, is there a way how to "chain" instance methods so I don't have to reference myObject multiple times? I am looking for something like
myObject.Read().Open(param1);
I can write myObject.Open(param1).Read(); which compiles however Read() is not executed.
//myObject.Open(param1).Read(); does execute but it's executed as StreamReader method not ReadTheFile method. Overlooked VS help...
class TestT211
{
static void Main(string[] args)
{
var myObject = new ReadTheFile();
myObject.Read(myObject.Open(#"C:\file.txt"));
}
}
public class ReadTheFile
{
private int _lineCounter = 0;
private string _lineOfText;
public StreamReader Open(string path)
{
return new StreamReader(path);
}
public void Read(StreamReader sr)
{
while ((_lineOfText = sr.ReadLine()) != null) {
Console.WriteLine(_lineOfText);
}
}
}
If you want to have a syntax like a Fluent API you need to change some point of your class. First you need to have Open return the current instance and then use that instance to call Read. But this assumes that you keep the StreamReader as an internal variable of the class
public class ReadTheFile : IDisposable
{
private int _lineCounter = 0;
private string _lineOfText;
private StreamReader _sr = null;
public ReadTheFile Open(string path)
{
_sr = new StreamReader(path);
return this;
}
public void Read()
{
if(_sr == null) return;
while ((_lineOfText = _sr.ReadLine()) != null) {
Console.WriteLine(_lineOfText);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if(_sr != null)
{
_sr.Close();
_sr = null;
}
}
}
}
and now you can write
using(ReadTheFile myObject = new ReadTheFile())
myObject.Open(#"C:\file.txt").Read();
Notice that having a StreamReader between your internal variables requires you to implement the IDisposable interface to properly close and dispose the Stream
If you want to add more functionality to class without access to it, you can use extensions. For example to use ReadTheFile to read StreamReader.
public static class StreamReaderExtension
{
public static StreamReader ReadEx(this StreamReader sr)
{
var readTheFile = new ReadTheFile();
readTheFile.Read(sr);
return sr;
}
}
and than call it with
myObject.Open(#"C:\file.txt").ReadEx();
You can add more methods, but cannot override the instance ones so you have to create a new name or new signature.
Using simple builder (it's overkill) but you could achive what you want:
class TestT211
{
static void Main(string[] args)
{
FileReaderBuilder.New.Open(#"C:\file.txt").Read();
}
}
public class ReadTheFile
{
private int _lineCounter = 0;
private string _lineOfText;
public StreamReader Open(string path)
{
return new StreamReader(path);
}
public void Read(StreamReader sr)
{
while ((_lineOfText = sr.ReadLine()) != null)
{
Console.WriteLine(_lineOfText);
}
}
}
public class FileReaderBuilder
{
private readonly ReadTheFile _file;
private StreamReader _streamReader;
private FileReaderBuilder()
{
_file = new ReadTheFile();
}
public FileReaderBuilder Open(string path)
{
_streamReader = _file.Open(path);
return this;
}
public FileReaderBuilder Read()
{
if (_streamReader == null)
{
throw new ArgumentNullException(nameof(_streamReader));
}
_file.Read(_streamReader);
return this;
}
public static FileReaderBuilder New => new FileReaderBuilder();
}
I am writing a small program in C# and at the start i noticed that Visual studio is complaining about having to use only static variables and static function calls in static functions (including the main). I have coded before, although i have to mention that i have coded before, and i cant remember being forced to use static everywhere. Here is the code:
class Program
{
string word = "asd";
static List<string> words = new List<string>();
static void Main(string[] args)
{
OpenFile();
Debug.WriteLine(words.Count);
anagram();
}
public static void OpenFile()
{
using (var fileStream = File.OpenRead("wordlist.txt"))
using (var streamReader = new StreamReader(fileStream))
{
String line;
while ((line = streamReader.ReadLine()) != null)
{
words.Add(line);
}
}
}
public void anagram()
{
Console.WriteLine(word);
}
}
I am getting the error " Error CS0120 An object reference is required for the non-static field, method, or property 'Program.anagram()' " and i just dont understand why? Also i wanted to make the words variable non-static as well but since the method is static that i am using it in it "has to be". Is there any way to avoid this?
I think i have a good understanding of what static is but i just don't want to use it here.
Any help is appreciated an thank you in advance.
You can define your logic into another class and create an instance of it and use its members.
public class MyClass
{
string word = "asd";
public List<string> Words = new List<string>();
public void OpenFile()
{
using (var fileStream = File.OpenRead("wordlist.txt"))
using (var streamReader = new StreamReader(fileStream))
{
String line;
while ((line = streamReader.ReadLine()) != null)
{
Words.Add(line);
}
}
}
public void anagram()
{
Console.WriteLine(word);
}
}
Then your main method would be like this:
static void Main(string[] args)
{
var m = new MyClass();
m.OpenFile();
Debug.WriteLine(m.Words.Count);
m.anagram();
}
You should read more about access modifiers and how static members and instance members are different.
You could write your class like this:
class Program
{
public string word = "asd";
public List<string> words = new List<string>();
static void Main(string[] args)
{
var program = new Program();
program.OpenFile();
Debug.WriteLine(program.words.Count);
program.anagram();
}
public void OpenFile()
{
using (var fileStream = File.OpenRead("wordlist.txt"))
using (var streamReader = new StreamReader(fileStream))
{
String line;
while ((line = streamReader.ReadLine()) != null)
{
this.words.Add(line);
}
}
}
public void anagram()
{
Console.WriteLine(this.word);
}
}
Static methods are generic to the class - if you want to use non-static, you need to instantiate an instance of it.
I've created a method in a class and I want to access the streamreader sr1 from another method within the same class but I can't seem to get access to the method!
public void showSelectedFile()
{
StreamReader sr1 = new StreamReader(File.OpenRead(ReturnTxt));
ReturnContenctRD = sr1.ReadToEnd();
}
public void DisposeSR1()
{
}
Can anyone explain to me how to access/alter these methods from other functions?
sr1 is local to the showSelectedFile() method; it goes out of scope when the method returns. If you want to make it visible to the other method, you have to make it a member of your class:
StreamReader sr1;
public void showSelectedFile()
{
sr1 = new StreamReader(File.OpenRead(ReturnTxt))
ReturnContenctRD = sr1.ReadToEnd();
}
public void DisposeSR1()
{
}
If it's just a matter of disposing it properly, wrap it in a using statement:
public void showSelectedFile()
{
using (StreamReader sr1 = new StreamReader(File.OpenRead(ReturnTxt)))
{
ReturnContenctRD = sr1.ReadToEnd();
}
}
You need to store the StreamReader in a class member variable
e.g.
class YourClass
{
private StreamReader _sr1;
public void showSelectedFile()
{
_sr1 = new StreamReader(File.OpenRead(ReturnTxt));
ReturnContenctRD = _sr1.ReadToEnd();
}
public void DisposeSR1()
{
if(_sr1 != null)
_sr1.Dispose()
}
}
I have the following code:
public class AppDomainArgs : MarshalByRefObject {
public string myString;
}
static AppDomainArgs ada = new AppDomainArgs() { myString = "abc" };
static void Main(string[] args) {
AppDomain domain = AppDomain.CreateDomain("Domain666");
domain.DoCallBack(MyNewAppDomainMethod);
Console.WriteLine(ada.myString);
Console.ReadKey();
AppDomain.Unload(domain);
}
static void MyNewAppDomainMethod() {
ada.myString = "working!";
}
I thought make this would make my ada.myString have "working!" on the main appdomain, but it doesn't. I thought that by inhering from MarshalByRefObject any changes made on the 2nd appdomain would reflect also in the original one(I thought this would be just a proxy to the real object on the main appdomain!)?
Thanks
The problem in your code is that you never actually pass the object over the boundary; thus you have two ada instances, one in each app-domain (the static field initializer runs on both app-domains). You will need to pass the instance over the boundary for the MarshalByRefObject magic to kick in.
For example:
using System;
class MyBoundaryObject : MarshalByRefObject {
public void SomeMethod(AppDomainArgs ada) {
Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + "; executing");
ada.myString = "working!";
}
}
public class AppDomainArgs : MarshalByRefObject {
public string myString { get; set; }
}
static class Program {
static void Main() {
AppDomain domain = AppDomain.CreateDomain("Domain666");
MyBoundaryObject boundary = (MyBoundaryObject)
domain.CreateInstanceAndUnwrap(
typeof(MyBoundaryObject).Assembly.FullName,
typeof(MyBoundaryObject).FullName);
AppDomainArgs ada = new AppDomainArgs();
ada.myString = "abc";
Console.WriteLine("Before: " + ada.myString);
boundary.SomeMethod(ada);
Console.WriteLine("After: " + ada.myString);
Console.ReadKey();
AppDomain.Unload(domain);
}
}