In the Program.cs for .NET 5, you could add methods under the Main(string[] args) method. With .NET 6, the Main method exists, but isn't physically included in the Program.cs file by default. To that end, I'm wondering how you add methods to Program.cs. For example:
// .NET 5
public class Program
{
static void Main(string[] args)
{
// body
}
public static void MyMethodHere()
{
// method body
}
}
How would you add the MyMethodHere() class in .NET 6 in Program.cs without manually typing out the whole Program class and Main method?
You just type out the method that you require and then call it!.
Console.WriteLine("Hello, World from Main!");
MyMethodHere();
static void MyMethodHere()
{
Console.WriteLine("MyMethodHere says hello World!");
}
But you can still type it out in full the same as you done before.
What I have done several times for simple console programs is to create the project with .net 5, this then generates using the "old" template, and then I just update TargetFramework it to .net 6 before I do any coding.
See also the guide from MS: https://learn.microsoft.com/en-gb/dotnet/core/tutorials/top-level-templates
This would work as well:
SayHello();
void SayHello()
{
Console.WriteLine("Hello World");
}
Methods are possible, but without the access modifiers.
The compiler internally creates a static class.
.NET 6 has this new feature that allows minimal main. They unfortunately use it by default in new console projects. Its very confusing. Anyway you can write the old main just like you used to. You just have to type out all the code, or cut and paste from an old project
Related
I am using .Net 6.0
I have a file in my project : Program.cs, containing registration and mapping code for controllers and services.
like:
builder.Services.AddControllers();
builder.Services.AddServices();
Now, I want to write, test cases for these lines of code, but there is no any method to call from the [Fact] method, inside the program.cs. Not even the main() method.
Can somebody please put some light on how can we cover this code with our test cases ?
When you create a new web application in VS2022, there's a checkbox "Do not use top-level statements". If you leave it unchecked, you get what you're seeing in Program.cs. If you do check it, you'll get:
namespace WebApplication1
{
public class Program
{
public static void Main(string[] args)
{
/* Everything exactly as you see in your Program.cs, but indented */
}
}
}
So if you do envisage wanting to call this method in tests (slightly odd, but okay), I'd recommend using this option rather than creating a separate method to call from Program.cs.
Even if you do get that checkbox option wrong during project creation, you should hopefully see that it's not tricky to transform between the two forms, using the above as a template (and adjusting namespace name)
Followed below steps to complete my code coverage:
Created an extension method for WebApplicationBuilder within a new static class.
Moved the testable code from Program.cs to the extension method.
Wrote the test cases for the extension method.
I just created my first .NET 6 console app, and instead of the default,
using System;
using System.Collections.Generic;
using System.Linq;
namespace MyApp
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
I got:
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
And even when there's no class, the program runs! I took a look at the link provided in the comments, but I don't know if this is a new feature or an old one. If this is a new feature, does that mean C# will be allowing C-style programming hereafter?
It's a new feature of C# 9 or 10. Microsoft documentation says following:
Top-level statements enable you to avoid the extra ceremony required by placing your program's entry point in a static method in a class. The typical starting point for a new console application looks like the following code:
using System;
namespace Application
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
The preceding code is the result of running the dotnet new console command and creating a new console application. Those 11 lines contain only one line of executable code. You can simplify that program with the new top-level statements feature. That enables you to remove all but two of the lines in this program:
Console.WriteLine("Hello, World!");
This is really a need because some third-party code like log4net can somehow run its code even before the static constructor of Program?
I've tried embedding log4net.dll as resource of the project and dynamically load it when needed using event handler for AppDomain.AssemblyResolve. However the soonest point in program I can inject here is in the static constructor of Program (to register the event handler):
static class Program {
static Program(){
AppDomain.CurrentDomain.AssemblyResolve += (s,e) => {
//...
};
}
}
But log4net is somehow even be involved/referenced before that point and that means it cannot be dynamically loaded, if not any raw dll found, a FileNotFoundException will be thrown.
Could you give me some suggest on what we can do in this case to run some code even before log4net? or generally as what I asked for, as soon as possible?
You can inject code even before that but not directly - VS doesn't allow that on it's own. You have to do it on IL level (by hand modifying IL code) or use some 3rd party tools that can do this - like Fody ModuleInit weaver.
What it does it will inject your code into the Module's code - the one that's visible in disassemblers as <Module>. This code will be executed when your module is loaded so it will be before static ctor.
Having such code:
using System;
namespace ConsoleApp3
{
class Program
{
static Program()
{
Console.WriteLine("static ctor of Program");
}
static void Main(string[] args)
{
Console.WriteLine("Main");
}
}
public static class ModuleInitializer
{
public static void Initialize()
{
Console.WriteLine("Module Initializer");
}
}
}
and Fody & Module Init as nuget packages installed will yield
Additionally, Fody has a module that does that what it looks like you need - Costura can pack all external dependencies into resources.
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.
I want to write a helper function start that starts pool threads for me but also adds some code before the actual background processing starts in the very same pool thread. So the background thread must do some extra work. I would call start very often and the extra code might change. So I wanted create a kinda factory for pool threads.
Would that be even possible ? If yes, how would I "inject" code into threads ?
I tried this:
class Program
{
private static void test()
{
Console.WriteLine("hello world");
}
private static void start1(Action param1)
{
ThreadPool.QueueUserWorkItem(o =>
{
// extra work is here
param1.Invoke(); // starts another subthread ?
});
}
private static void start2(WaitCallback param1)
{
ThreadPool.QueueUserWorkItem(param1);
}
static void Main(string[] args)
{
start1(new Action(test));
start2(o => { test(); });
Console.ReadKey();
}
}
ThreadPool.QueueUserWorkItem(o =>
{
ExtraWork();
param1.Invoke();
});
is equivalent to
ThreadPool.QueueUserWorkItem(o =>
{
ExtraWork();
param1();
});
Invoking a delegate does not start a new thread. (Why do you think it might?) So this code works just fine as it is. It will invoke the two functions sequentially.
You cannot add random. net code to run by string value. Unless you play with compiler and take the code, compile it into a DLL then call it with reflection i don't see how it can be done. If that's what you need i am scared to ask how the hell you need to do that.
If you do not require to have random code but specific functions well it's your lucky day. Functions can be pass as parameters. you can also build a list of function to get called in order and do it. That you will need to do more search on that, i haven't done this in years. Or maybe fellow stacker can comment and add link to nice article.
If the code need to be randomly generated and is not forced to be .net, example listing file in directory, opening program. Well you can look into scripting language. Worst case you can build a .vbs (Visual Basic Script) dynamically and run it. Then wait for it to create a text file for the results and read it to know what happened.