How do I access a class from Main in console app? - c#

I'm playing with my first console app -- though I've been developing ASP.NET apps for years.
I see lots of examples where all the simple logic is placed in the Main method. I wanted to create a separate DoSomething.cs class and put my logic in a method called DoThisFirst() then call it from the Main but I can't see the DoThisFirst() method from Main(). What am I doing wrong?
class Program
{
static void Main(string[] args)
{
// I want to call DoThisFirst() method from here. What do I need to do?
}
}
class DoSomething
{
static void DoThisFirst()
{
Console.WriteLine("It worked!");
Console.ReadKey();
}
}

The method DoThisFirstis is private, as that is the default accessibility for members of a class. You'll need to make it public (or at least something more than private) to access it from another class.

Related

Display custom warning at compile time related to method implementation in C#

In the current context we have two methods Start and Stop. These two methods are invoked from a function sequentially. There can be chances that a person invokes just Start() inside his method but forgets to invoke Stop(). e.g.
private void A()
{
Start();
//Buisness logic goes here
}
In this context when the code is compiled a warning or error needs to be displayed informing that for every Start() there should be a corresponding Stop(). Can somebody suggest ideas on how to go about implementing the same in C#?
The proper way of implementation would be
private void A()
{
Start();
//Buisness logic goes here
Stop();
}
I would suggest you change your pattern to take care of the Start and Stop without ever exposing it to the programmer.
Change your class implementing Start & Stop to implementing an Execute method instead and dont even expose the Start & Stop.
public class MyClass
{
private void Start(){} // old public method
private void Stop(){} // old public method
public void Execute(Action action)
{
Start();
action();
Stop();
}
}
Usage:
var impl = new MyClass();
impl.Execute(() => {
// do something in between start & stop
});
Evk gave a good hint, here is how I would do it in more detail:
Have a class (e.g. StartStop ) implement IDisposable
public class StartStop : IDisposable
{
public StartStop() { Start(); }
public void Dispose() { Stop(); }
protected void Start() { /*...*/ }
protected void Stop() { /*...*/ }
}
Make use of this class with using:
private void A()
{
using( var startStopCaller = new StartStopCaller() )
{
// Your code here
}
}
using will make sure Dispose() and subsequently Stop() will be called except for hard crashes.
This can be approached in many ways, with two primary directions:
If you're using the later versions of the .NET platform, and thus the Roslyn compiler (Defaults from VS2015 and onwards), you can look into writing a compiler plugin that checks this for you. Here are some resources:
Introduction to Scripting with the .NET Compiler Platform (Roslyn)
.NET Compiler Platform SDK
Probably a lot more out there, if you search for "Roslyn" or ".NET Compiler platform".
As some of the comments you got are pointing out, this could be fixed in your code and program design. This is most probably the "correct" way to approach this. Some examples:
Consider implementing IDisposable and use your class in a using statement - however, remember that stopping and disposing of an object might not be the same here. You should make an informed desicion about this with the knowledge you have about the inner workings of your program.
If you're calling these classes from elsewhere, you could let them implement an interface containing both your Start and Stop methods. And then let the calling class simply treat them as this interface, and make sure it calls both methods no matter which implementation it uses.
Re-architect your code to not depend upon running Start() and Stop() sequentially. This might require fundamental design changes to your program and how it works, but it might just be worth it. Both for readability and maintainability.

c# static object reference

I have a class like so
public class FileLogger
{
public FileLogger(string typeOfLog)
{
//implementation
}
public void LogError(string err)
{
//implementation
}
public void LogMessage(string err)
{
//implementation
}
}
Since this is a logging class for an application to log its output to a file, one would have expected it to be a static class. However as you can see it is not. It is however used in the application like this:
public class BugetApplication
{
private static FileLogger logger;
//constructor
public BugetApplicationClass()
{
logger = new FileLogger("some-constructor-parameter");
}
//a method that uses the FileLogger class for logging
public string Classify()
{
try
{
//start multiple threads for classification
Classification clsf = new Classification();
clsf.handleEvent += clsf_handleEvent;
clsf.Classify();
}
catch (Exception exp)
{
logger.LogError(exp.Message);
}
}
private static void clsf_handleEvent(string errString)
{
if(errString.Contains("error"))
{
logger.LogError(errString);
}
}
}
Multiple threads are started by the BugetApplication class's classify method. Any errors in that class fire an event which is handled in the BugetApplication class's clsf_handleEvent method. So multiple threads could each fire their own event. Would creating the instance variable as a static variable in the BugetApplication class have any effect here or would keeping it non static have the same effect? I don't want any one thread to overwrite the error message of another thread.
Edit
Just to clear things out, the BugetApplication class which will be created only once has a static variable 'static FileLogger logger; ' it creates an instance once in its constructor, passing in some values to the constructor of the FileLogger class. In the BugetApplication class, there is a method which calls the Classification class's classify method. The Classify method starts the various threads and on any error fires an event which is handled back in the BugetApplication class so this clsf_handleEvent method can have multiple calls on it.
Why do you think it would overwrite the error message of another thread? The logger should just append the messages, so there shouldn't be any overwriting (depends how you handle the logging though). There is a potential problem however - depending on your logging function you might be blocking access to the file. Because the method works on an external file, you should probably use lock in the function.
It really doesn't matter if the class is static or not, the problem is concurrent access to external resources which needs to be synchronized for multiple threads to become thread-safe.
lock documentation on msdn
It really depends on the actual implementation of the logger.
Static classes are now frowned upon as they make unit testing more difficult. Many facilities which conventionally were implemented as static or singleton (loggers, e-mailers, etc.) now provide unit test/IoC friendly alternatives (e.g. a factory and an interface or virtual class).
The design of these facilities is usually a front end class which the client application uses to interact and an asynchronous back end which takes care of the synchronization and actual logging (or emailing, or whatever).
The crux is whether the front ends are multi-threaded or not.
If they are not; you should create a new one per thread. In this case the logger would probably have to be a local variable or parameter of the method using it.
Usually, however, they are multi-threaded and re-entrant, as all they do is pass along the log message to the back-end and have no state of their own. In this case they can be saved as a static variable or application wide singleton, but it is better to instantiate them in an IoC container as singleton and inject it to the classes using them. Doing so makes writing unit tests with mock loggers a lot easier.

How do I communicate with a control of a Form from another class?

A little new to C#, and approaching something beyond me. Apologies for length.
I have a Windows Form application in Visual Studio C# Express, using the default classes VS spawns. I want to start and stop a Marquee style progressBar from a class other than the default Form1 in which it is declared.
These seems surprisingly difficult, I am sure I am missing something important.
My project has the usual classes that Visual Studio auto generates:
Form1.cs, Form1.Designer.cs , Program.cs .
I added myClass.cs that wants to talk the load bar.
I add progressBar1 bar to my form using the designer, setting Style:Marquee.
In Form1.cs' Form() constructor, I write
this.progressBar1.Visible = false;
This works. Intellisense 'sees' progresBar1.
code in Form1.cs can see and control progressBar1 declared in Form1.Designer.cs.
this makes sense to me.
But the functions which need to start and stop the load bar must live in myClass.cs.
I want to be able to code like this, within myClass.cs:
public void myFunction(){
Form1.progressBar1.visible=true
//do stuff that takes a bit of time
Form1.progressBar1.visible=false
}
This does not work. Intellisense cannot 'see' progresBar1 when typing code in myClass.cs.
In fact, intellisense cannot 'see' anything in Form1.cs from within myClass.cs.
No public propeties or functions added to Form1 ever become visible to intellisense.
This does not make sense to me, I am confused.
This seems like something you would want to do often and easily.
Some searching indicates that this blocking of external access to Form controls is by design. Something to do with 'decoupling' your logic code from GUI code, which makes sense in principal.So clearly there is an expected approach, yet an clear example is hard to find. I can only find examples of loadbars controlled from entirely within the Forms that declare them, or terse half-examples about creating and registering Events or using Invoke or other things I know too little about. There are many apparent solutions but none that I can see clearly apply to me, or that I am able to implement, in my ignorance.
I think I could do it if my Form were an instance.
[EDIT] nope. instance or not, Form1 controls never become exposed outside of Form1.cs
So, How do I to start and stop a Marquee style progressBar from a class other than the default Form1 in which it is declared, in the proper way?
Is there a clear and useful example somewhere?
You can't access your properties this way:
Form1.progressBar1
because Form1 is a type (not an instantiated object). The only methods or properties you can access with this approach have to be marked as static.
To answer your question of how to communicate, you probably want to use the event approach that you mentioned. First you need an event in your logic class:
public event Action<int> UpdateProgress;
Which is called just like a function:
if (UpdateProgress != null)
UpdateProgress(10);
This declares a new event using the Action generic delegate, which means the listening function has to return void and take one int as a parameter.
Then in your forms code, you'll have:
MyClass logic = new MyClass();
private void SomeFunction
{
logic.UpdateProgress += UpdateProgressBar;
}
private void UpdateProgressBar(int newProgress)
{
progressBar1.BeginInvoke(new Action(() =>
{
progressBar1.Value = newProgress;
}));
}
This creates a new instance of your logic class, and assigns the function "UpdateProgressBar" to be called whenever your logic class raises the UpdateProgressBar event. The function itself uses Dispatcher.BeginInvoke because your logic class is likely not running on the UI thread, and you can only do UI tasks from that thread.
There is a lot going on here, so please let me know if I can clarify anything for you!
I would create a model that has properties matching your form, and pass that around.
So you would make a new class like this...
using Windows.Forms;
public class Form1Model {
public ProgressBar progressBar { get; set; }
}
Then when you want to get to your other class holding that function you would create an instance of Form1Model, fill it, and call your function
var fm = new Form1Model {
progressBar = this.progressBar1;
};
otherClass.MyFunction(fm);
now you would have to change your function to accept the new model
public void MyFunction(Form1Model fm){
// do stuff
}
Another option is just making the function take an instance of the form, and not creating a model, but then you are going to be passing a lot of extra bits you probably won't care about
public void MyFunction(Form1 form){
// do stuff
}
Then on your form you would call the function like this
otherClass.myFunction(this);
I would recommend the first way over the second, you can control what data is being passed around
You are trying to access the type Form1 instead of the forms instance. I'll show you, how you can access the instance below.
I assume that Form1 is the applications main form that stays open as long as the application runs. When you create a WinForms application VS creates this code in Program.cs:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
A simple way to make your main form accessible throughout the application is to make it accessible via a public static property. Change the code like this
static class Program
{
public static Form1 MainForm { get; private set; }
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MainForm = new Form1();
Application.Run(MainForm);
}
}
In Form1 create a property that exposes the progress bar's visibility:
public bool IsProgressBarVisible
{
get { return this.progressBar1.Visible; }
set { this.progressBar1.Visible = value; }
}
Now you can make the progress bar visible from any part of the program like this:
Program.MainForm.IsProgressBarVisible = true;
Another way of accessing the main form is, since it is always opened as the first form:
((Form1)Application.OpenForms(0)).IsProgressBarVisible = true;
However, it requires the form to be casted to the right type, since OpenForms returns a Form.
And don't forget: A Form is just a class like any other class. You can do almost everything you can make with other classes. So, communicating with forms is not very different than communication with other objects, as long as you are not using multithreading.

Code starts only when Application.Run() is invoked WPF application

I have a method which is invoked in class A and it is defined in class B:
class B{
[STAThread]
public static void ScanForAxisCameras() {
DNSSDService service = new DNSSDService();
DNSSDEventManager eventManager = new DNSSDEventManager();
eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(eventManager_ServiceFound);
DNSSDService browse = service.Browse(0, 0, "_axis-video._tcp", null, eventManager);
Application.Run();//if not invoked everything above does not start
}
}
class A{ ...before invoking..... B.ScanForAxisCameras(); ....after invoking....}
The code in class B "starts"/works only if I invoke Application.Run(). But it causes that all the code in class A ....after invoking.... method does not work. How to handle it so it will not freeze the application?
Edit: the class A is class MainWindow.xaml.cs. It is WPF application.
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
createGUI();
}
private void createGUI() {
LocalNetworkScanner.ScanForAxisCameras();//when there is no Application.Run() ScanForAxisCameras() does not work.
}
}
The WPF UI thread on which you call ScanForAxisCameras() already has a message loop. I believe the problem with your code is that all objects you create inside ScanForAxisCameras have the local scope:
public static void ScanForAxisCameras() {
DNSSDService service = new DNSSDService();
DNSSDEventManager eventManager = new DNSSDEventManager();
eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(eventManager_ServiceFound);
DNSSDService browse = service.Browse(0, 0, "_axis-video._tcp", null, eventManager);
Application.Run();//if not invoked everything above does not start
}
Without Application.Run(), your objects (service, eventManager, browse) may be getting destroyed and finalized as soon as ScanForAxisCameras finishes. So, the events you're looking for (like ServiceFound) may not even have a chance to get fired.
If you call Application.Run(), then ScanForAxisCameras doesn't exit (at least not until Application.Run() itself exits). That keeps your objects alive and functional.
Try refactoring your code to keep the references to these objects in member fields of your class (or in static variables, FWIW). I believe that should fix the problem.
[EDITED] On a side note, the [STAThread] attribute doesn't make sense in that context (unless you use ScanForAxisCameras as an entry point for a new thread - apparently, that's not the case here).
You can introduce a new Run()-method in your App in the App.xaml.cs file.
Here you can perform custom actions before the application itself gets initialized.
Further information here.
public partial class App : Application
{
public new void Run()
{
// Do your stuff here
B.DoStuff();
// Call the base method
base.Run();
}
}
Application.Run starts the message loop for that particular thread, if there is no message loop then there is no notification for your objects to know they have to do something.
The code in class B "starts"/works only if I invoke Application.Run(). But it causes that all the code in class A ....after invoking.... method does not work.
Run is a blocking call therefore any code after that call is not reachable until the application is closing down i.e. when you exit the message loop.
How to handle it so it will not freeze the application?
In short, you can't. Run will always block so any code you need to run as part of your application startup will have to happen before the call.
After your edit to mention that this is a WPF application then Application.Run as a static method is not the right way to go here. If you need to run initialization when your application starts then you can do what has already been suggested and override the Run method of the Application class, or alternatively (maybe more appropriately) you can hook into the OnStartup event e.g.
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
// code before startup
base.OnStartup(e);
// code after startup
}
}
It seems as though in this situation you would need to add Application.Run() in a different class. Run() accepts nothing, ApplicationContext, Form. This controls the lifetime of the application and should be called before class A, unless class A is the entry point.
See http://msdn.microsoft.com/en-us/library/ms157900.aspx for details.
A Windows Forms application starts when the Main method is called. You can implement initialization procedures on the Main function. However, to initialize a Windows Forms application fully and start it routing Windows Forms events, you need to invoke Application.Run.
you can read about Application here

basic c# architecture and class handling question

Ok guys, this is very basic stuff I think.
I'm only getting familiar with C# and object oriented languages.
So here is a basic project I'm developping :
namespace MyProject
{
class MyProject
{
public Logger Logs = new Logger();
public WebServer Web = new WebServer();
static void Main()
{
// blabla
}
}
}
The logger is there to simply create a log file and when its "Add(string str)" method is called, it adds a line in the log file.
The webserver is my own webserver, opening a socket etc ...
I'd like my webserver to be able to use my Add method of the logger... how am I supposed to achieve that ?
Inside my webserver class, using something like "MyProject.Logs.Add(string str)" doesn't seem to work.
So how can I reference it ?
I don't want to create a new instance of my Logger class inside my webserver, because I want to write everyting in the same text file (I might have more module running than just a webserver as well).
So I'd like to use the instance I created in my Main method, inside my Webserver class...
I hope this makes sense ...
A couple of suggestions:
Logs and Web should be private. Those are implementation details of your class. They're nobody else's business.
Pass the instance of your logger to your web server:
public WebServer Web = new WebServer(Logs);
Your web server can now have its very own copy:
private Logger Logs {get;set;}
public WebServer(Logger logs)
{
Logs = logs;
}
public void DoSomething()
{
Logs.Add("I did something!");
}
MyProject.Logs.Add(string str) does not work because Logs member is not static, which means it can be different for different instances of your class (which are created by operator new). The compiler can't know which instance you are referring to if you don't specify it.
If you mark Logs as static, then it will work.
However, making it static makes your project less customizable (for example you will not be able to start two web-servers with two different log-files in the same program). That's why what John Saunders suggested is usually considered better.
You can do this easily by passing a reference to the Logger instance you created in within MyProject to your instance of WebServer.
In your WebServer class, you can make a property (a getter/setter) of type Logger, so that WebServer knows about the Logger you want to use. Another alternative (probably better) is to add a parameter to the constructor of WebServer that takes the Logger. Pseudo code for adding the property:
public class WebServer
{
public WebServer(Logger l)
{
Log = l;
}
//relevant code....
public Logger Log { get; set; } //Short hand property declaration, see http://msdn.microsoft.com/en-us/library/bb384054.aspx
}
From inside the WebServer class, you can use the logger like Logger.Add("some text...");
Then, in your Main method, you can pass in your instance of Logger like so:
namespace MyProject
{
class MyProject
{
public static Logger Logs = new Logger();
public static WebServer Web;
static void Main()
{
Web = new WebServer(Logs);
}
}
}

Categories

Resources