How to use a method in other classes? - c#

I have a method that I want to use in almost all the classes within a same c# project.
public void Log(String line)
{
var file = System.IO.Path.GetPathRoot(Environment.SystemDirectory)+ "Logs.txt";
StreamWriter logfile = new StreamWriter(file, true);
// Write to the file:
logfile.WriteLine(DateTime.Now);
logfile.WriteLine(line);
logfile.WriteLine();
// Close the stream:
logfile.Close();
}
What is the approach to reuse this method in other classes of the project?

If you want to use it in all classes, then make it static.
You could have a static LogHelper class to better organise it, like:
public static class LogHelper
{
public static void Log(String line)
{
var file = System.IO.Path.GetPathRoot(Environment.SystemDirectory)+ "Logs.txt";
StreamWriter logfile = new StreamWriter(file, true);
// Write to the file:
logfile.WriteLine(DateTime.Now);
logfile.WriteLine(line);
logfile.WriteLine();
// Close the stream:
logfile.Close();
}
}
Then call it by doing LogHelper.Log(line)

You can make a static class and put this function in that class.
public static MyStaticClass
{
public static void Log(String line)
{
// your code
}
}
Now you can call it elsewhere. (No need to instantiate because it's a static class)
MyStaticClass.Log("somestring");

You can use Extrension method in statis class
Sample on string extension
public static class MyExtensions
{
public static int YourMethod(this String str)
{
}
}
link : http://msdn.microsoft.com/fr-fr/library/vstudio/bb383977.aspx

Related

How to get generic type from one class to another c#

Is it possible to pass the generic type from one class to other class generic property.
For example:
Assembly Logger
namespace Logger
{
public class GenericLoger<T>
{
T _genericLog;
LogManager _logManager;
public GenericLoger(string logName)
{
_logManager = new LogManager(logName);
//Assigning the generic type to Log.GenerciLog, this is how I am
expecting or by some other possible way?.
Log.GenerciLog = _genericLog;
}
public static Write(string description)
{
_logManager.write(description);
}
}
public static class Log
{
LogManager _logManager;
static Log()
{
_logManager = new LogManager();
}
public static Write(string description)
{
_logManager.write(description);
}
//The generic type supplied in GenericLoger need to pass here,
//like this or by some other possible way?
public static T GenerciLog { get; internal set; }
//T is unrecognized here as type is available in GenericLoger
//I want to pass here from GenericLoger
}
}
Assembly Main Caller of Logger
using Logger;
namespace DataProcessor
{
internal class SpecialLogger
{
private static Lazy<GenericLog<SpecialLogger>> _passed;
public static GenericLog<SpecialLogger> Passed
{
get
{
if (_passed == null)
{
_passed = new Lazy<GenericLog<SpecialLogger>>(() => new GenericLog<SpecialLogger>("Passed"), true);
}
return _passed.Value;
}
}
private static Lazy<GenericLog<SpecialLogger>> _failed;
public static GenericLog<SpecialLogger> Failed
{
get
{
if (_failed == null)
{
_failed = new Lazy<GenericLog<SpecialLogger>>(() => new GenericLog<SpecialLogger>("Failed"), true);
}
return _failed.Value;
}
}
}
internal class Processor
{
public void ProcessRate()
{
var trans = dataManager.GetData();
//Will write the log in "Log.txt" file
Log.write(trans.Count + " transaction found");
foreach (var item in trans)
{
try
{
//transaction process code here
//This will write the text in "Passed.txt" file. 'Passed' property I want to access like this
Log.GenerciLog.Passed.Write(item);
}
catch (Exception ex)
{
//This will write the text in "Failed.txt" file. 'Failed' property I want to access like this
Log.GenerciLog.Failed.Write(item);
}
}
}
}
}
NOTE: In .NET you don't have a way for automatic type inference for use case like yours, also there is no automatic type substitution.
Not sure if this is what you are looking for
Your method definition should look like this
public static T GenerciLog<T> { get; internal set; }
and this is how to call it
try
{
//transaction process code here
//This will write the text in "Passed.txt" file. 'Passed' method I want to access like this
Log.GenerciLog<SpecialLogger>.Passed.Write(item);
}
catch (Exception ex)
{
//This will write the text in "Failed.txt" file. 'Failed' method I want to access like this
Log.GenerciLog<SpecialLogger>.Failed.Write(item);
}
This is a very simple log class. There is a lot more you could do with this sort of thing. Its all provided by log4net which I'd recommend using rather than trying to write your own logger. But the below is a start of how I'd implement a simple logger. It allows you to log to several different things at once. I appreciate the below doesn't answer exactly what you want but its an indication of how to start and you can adapt it to suit your needs.
public static class Logger
{
private static List<ILogger> _loggers = new List<ILogger>();
public static void Log(string message)
{
foreach (var logger in _loggers)
logger.Write(message);
}
public static void AddLogger(ILogger logger)
{
_loggers.Add(logger);
}
}
public interface ILogger
{
void Write(string message);
}
public class SpecialLogger : ILogger
{
public void Write(string message)
{
//special log code here eg
Console.WriteLine(message);
}
}
then somewhere do this
Logger.AddLogger(new SpecialLogger());
Logger.Log("A log message");

How to mock the StringBuilder class

Per this answer, I would like to know how to mock a StringBuilder class. The way they are mocking the Console class is brilliant:
You need an interface defining your dependency:
public interface IConsoleService
{
string ReadLine();
void WriteLine(string message);
}
You create a default implementation for it:
public class ConsoleService : IConsoleService
{
public string ReadLine()
{
return Console.ReadLine();
}
public void WriteLine(string message)
{
Console.WriteLine(message);
}
}
What would be the approach to mocking the StringBuilder.Append method?
So far what I have is this:
public interface IStringBuilderService
{
string Append(string line);
StringBuilder s
}
public class StringBuilderService : IStringBuilderService
{
public string Append(string line)
{
return this.ToString() += line;
}
}
Even though, there is rarely a need to mock StringBuilder, I'll assume you need it for trial purpose.. so here is one possible way to mock it.
Your default implementation class needs to wrap an instance of StringBuilder.
public interface IStringBuilderService
{
IStringBuilderService Append(string line); // mimic the StringBuilder Append signature
StringBuilder S { get; }
}
public class StringBuilderService : IStringBuilderService
{
private StringBuilder _actualStringBuilder;
public StringBuilder S
{
get { return _actualStringBuilder; }
}
public StringBuilderService() // you could also take in a parameter if you wish to initialize the variable
{
_actualStringBuilder = new StringBuilder();
}
public IStringBuilderService Append(string line)
{
_actualStringBuilder.Append(line);
return this;
}
public override string ToString()
{
return _actualStringBuilder.ToString();
}
}
The reason we need an instance of StringBuilder wrapped up in the concrete class is because Console is a static resource, and hence accessed without an instance variable requirement. StringBuilder will be per instance, and hence we need a variable encapsulating that.
Once you have this interface, you can use this interface wherever StringBuilder manipulation is required.
And for your tests, you could use a mock of this interface.

c# Main Class include "subclass"

Hey I have two classes
class Main
{
public exLog exLog;
public Main()
{
}
}
and
class exLog
{
public exLog()
{
}
public exLog(String where)
{
}
public exLog(String where, String message)
{
}
}
i tried to call exLog direct without giving exLog a parameter. So I can call any class with the Main Method.
How should I do that?
public String ReadFileString(String fileType, String fileSaveLocation)
{
try
{
return "";
}
catch (Exception)
{
newMain.exLog("", "");
return null;
}
}
I like to call them like a funtion in Main
You can call it as soon as you instantiate it.
public Main()
{
exLog = new exLog();
exLog.MethodInClass();
}
Also, if you are not in the same assembly you'll need to make exLog public.
Finally, this is C# and the style dictates that class names should be PascalCased. It's a good habit to form.
Methinks you want something like Adapter Pattern
class Main
{
private exLog exLog;
public Main()
{
}
public void ExLog()
{
exLog = new exLog();
}
public void ExLog(String where)
{
exLog = new exLog(where);
}
public void ExLog(String where, String message)
{
exLog = new exLog(where, message);
}
}
I think you're confused about classes, instances, constructors, and methods. This does not work:
newMain.exLog("", "");
because exLog in this case is a property, not a method. (It's confusing because you use the same name for the class and the property, which is why most conventions discourage that).
You can call a method on the instance:
newMain.exLog.Log("", "");
but then you'll need to change the names of the methods (and add a return type) in your exLog class so they don't get interpreted as constructors:
class exLog
{
public void Log()
{
}
public void Log(String where)
{
}
public void Log(String where, String message)
{
}
}
class Main
{
public exLog exLog;
public Main()
{
exLog = new exLog();
exLog.ReadFileString("", "");
}
}

How attach event to console app on startup

I have application for which I need to add additional hidden logging.
I have put prototype in way.
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Start");
new DummyTest().Report();
Console.WriteLine("End");
Console.ReadKey();
}
}
public class DummyTest
{
public void Report()
{
var reporter = new Reporter();
Console.WriteLine("Reporting");
for (var i =0; i < 155; i++)
{
reporter.Process(i);
}
Console.WriteLine("Reporting end");
}
}
public class Reporter
{
// attach behavior here
public void Process(int requestId)
{
Console.WriteLine("Processing request: {0}" , requestId);
System.Threading.Thread.Sleep(100);
}
}
Now I have new project logger.dll that contains
using System;
namespace logger
{
public class Log
{
public Log()
{
Console.WriteLine("Line executed");
}
}
}
Now I would like to execute this method every time Main gets executed. This however cannot be referenced in any other way except only by referencing the dll.
=Update=
I do not mind to have reference to that dll. But in main code I cannot have any reference to Log. I thought about using reflection in order to make this work. The problem I am trying to solve first is how to attach that to the execution.
Why I cannot call logger from main?
This is supposed to be reporting on usage of the class, monitoring usage, in order to report on performance on bottle necks.
You could do something like this:
void Main()
{
System.Console.SetOut(new CustomTextWriter());
Console.WriteLine("test");
}
public class CustomTextWriter : TextWriter
{
private TextWriter _consoleOut = null;
private Log _logger = null;
public CustomTextWriter()
{
_consoleOut = System.Console.Out;
_logger = new Log();
}
public override void Write(char[] buffer, int index, int count)
{
this.Write(new String(buffer, index, count));
}
public override void Write(string value)
{
_consoleOut.Write(value);
_logger.Write(value);
}
public override void WriteLine(string value)
{
_consoleOut.WriteLine(value);
_logger.WriteLine(value);
}
public override Encoding Encoding
{
get { return System.Text.Encoding.Default; }
}
}
Wasn't sure if you wanted to do logging without actually calling Console.WriteLine() (if yes you'll need to look at Interception) but if that's ok then this should get you through.
Hope this helps.
You could do that with reflection like this:
// load the assembly
Assembly LogDll = Assembly.LoadFile(#"Log.dll");
// get the type of the Log class
Type LogType = LogDll.GetType("logger.Log");
// get instance of the Log class
object LogInstance = Activator.CreateInstance(LogType);
// invoke class member "Log()"
LogType.InvokeMember("Log",
BindingFlags.InvokeMethod |
BindingFlags.Instance |
BindingFlags.Public,
null,
LogInstance,
null);
Although I'm not sure if the constructor "Log()" already gets called by creating the instance. You should probably move your actual log method out of the constructor. To pass arguments you can use the last parameter of InvokeMember which is an array of the type Object.

Passing a variable from a public class to a public static class

I have a public class and need to use one of those variables inside a public static class. Is this possible? If so: how can I call it?
public class xmlData
{
public string testing;
}
public static class fileUpload
{
public static string uploadFile(string file)
// I want to use the testing here
}
You would inject an instance of the xmlData into the method. Like this:
public static string uploadFile(xmlData data, string file)
Now inside that method you can do this:
data.testing ...
To access instance field from static method is not possible. You can pass value as parameter:
public static string uploadFile(string file, string testing)
Or pass object into method:
public static string uploadFile(string file, xmlData data)
{ string testing = data.testing; }
of course it's possible. you just pass it in.
string myString = fileUpload.uploadFile(testing);
All of the methods I can think of in one single spot:
public class xmlData
{
public string testing;
// part of "first option"
public void RunStatic() {
fileUpload.uploadFile(testing);
}
}
public static class fileUpload
{
// used by "option 1, 3"
public static string uploadFile(string testing) {
var firstOption = testing;
}
// used by "option 2"
public static string uploadFile(xmlData myObject, string file) {
var secondOption = myObject.testing;
}
}
public class Program {
public static void Main() {
var objectExample = new xmlData();
// first example
objectExample.RunStatic();
// second example
fileUpload.uploadFile(objectExample, "");
// third example
fileUpload.uploadFile(objectExample.testing);
}
}
All of these will work and should hopefully answer the question. A different question might be whether or not its a good idea to expose instance variables directly or should a property be used. Hm.

Categories