Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# attribute over main

Someone asked me a question as to how we can print

line no 1
line no 2
line no 3

Without changing a main method which reads

static void Main(string[] args)
{
    Console.WriteLine("line no 2");
}

Now one approach was to have multiple entry points for the console application. However I tried another approach which goes as follows :

class Program
{
    [Some]
    static void Main(string[] args)
    {
        Console.WriteLine("line no 2");
    }
}
class SomeAttribute : Attribute
{
    public SomeAttribute()
    {
        Console.WriteLine("line no 1");
    }
    ~SomeAttribute()
    {
        Console.WriteLine("line no 3");
    }
}

When I apply a breakpoint on each of the WriteLine, I am able to see that the approach works, however, the same isn't reflected on the console.

Just curious.

like image 244
user2277247 Avatar asked Apr 13 '13 10:04

user2277247


1 Answers

You're problem can be broken down into the search of the hooks, which are triggered before and after Main method execution of the console application.

  • First hook is a Program static constructor, which is guarantee to execute before Main method in Program class.

  • Second is an event ProcessExit of a AppDomain, which "Occurs when the default application domain's parent process exits". You can use static constructor to subscribe to this event.


class Program
{
    static Program()
    {
        Console.WriteLine("line no 1");

        AppDomain.CurrentDomain.ProcessExit += 
                                          (s, a) => Console.WriteLine("line no 3");
    }

    static void Main(string[] args)
    {
        Console.WriteLine("line no 2");
    }
}

prints:

line no 1
line no 2
line no 3

Next part would be quite a long one. I'll try to explain what is the problem with SomeAttribute in your question.

First of all, consider this StackOverflow question to know exactly when custom attributes constructors are executed. This isn't so simple, as it might seem at first glance.

As we already know, ctor of custom attribute will only be executed, when you will access it via reflection. So in you example simple program execution won't trigger attribute constructor. But why do your breakpoint hit, when you apply SomeAttribute to Main method? It turns out, that visual studio uses reflexion to find out main method and attach a debugger to your application. But there is no console window at that point. So statement Console.WriteLine is useless and produce to effect. Moreover, it seems to block all next statements to console output.

So next code will produce different results, depending if you run it with VS debugger or not:

class Program
{
    [MyAttribute]
    static void Main()
    {

    }
}

class MyAttribute : Attribute
{
    public MyAttribute()
    {
        MessageBox.Show("MyAttribute ctor");
    } 
}

If you run it without debugger (Ctrl + F5 in VS default configuration), you'll see, that program terminates and no windows appear. When you execute it with debugger (F5) you'll see

enter image description here

and no console window next to VS, only win forms icon: enter image description here

As I've described earlier, when you try to write to console when there is no one, then all other calls to Console.WriteLine doesn't affect your console application. That's why you can see any console messages, even if you step a breakpoint in the constructor.

like image 176
Ilya Ivanov Avatar answered Oct 02 '22 00:10

Ilya Ivanov