use*_*247 9 c# attributes console.writeline
有人问我一个关于如何打印的问题
line no 1
line no 2
line no 3
Run Code Online (Sandbox Code Playgroud)
不改变读取的主要方法
static void Main(string[] args)
{
Console.WriteLine("line no 2");
}
Run Code Online (Sandbox Code Playgroud)
现在一种方法是为控制台应用程序提供多个入口点.但是我尝试了另一种方法,如下所示:
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");
}
}
Run Code Online (Sandbox Code Playgroud)
当我在每个WriteLine上应用断点时,我能够看到该方法有效,但是,控制台上没有反映出这一点.
只是好奇.
Ily*_*nov 15
您可以将问题分解为钩子的搜索,这些钩子Main在控制台应用程序的方法执行之前和之后被触发.
第一个钩子是Program静态构造函数,它保证在类中的方法之前 执行.MainProgram
二是事件ProcessExit 的AppDomain,其中"时默认应用程序域的父进程退出时".您可以使用静态构造函数来订阅此事件.
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");
}
}
Run Code Online (Sandbox Code Playgroud)
打印:
line no 1
line no 2
line no 3
Run Code Online (Sandbox Code Playgroud)
下一部分将是一个很长的部分.我会试着解释你问题SomeAttribute中的问题.
首先,请考虑此StackOverflow问题以确切了解何时执行自定义属性构造函数.这并不是那么简单,乍看之下似乎也是如此.
我们已经知道,只有当你通过反射访问它时,才会执行自定义属性的ctor.因此,在您的示例中,简单的程序执行不会触发属性构造函数.但是,为什么你遇到断点,当你申请SomeAttribute到Main的方法?事实证明,visual studio使用反射来找出主要方法并将调试器附加到您的应用程序.但是那时没有控制台窗口.因此,陈述Console.WriteLine是无用的,并产生效果.此外,它似乎阻止了控制台输出的所有下一个语句.
因此,下一代码将产生不同的结果,具体取决于您是否使用VS调试器运行它:
class Program
{
[MyAttribute]
static void Main()
{
}
}
class MyAttribute : Attribute
{
public MyAttribute()
{
MessageBox.Show("MyAttribute ctor");
}
}
Run Code Online (Sandbox Code Playgroud)
如果你在没有调试器的情况下运行它(VS默认配置中的Ctrl + F5),你会看到,该程序终止并且没有窗口出现.当你使用调试器(F5)执行它时,你会看到

并且VS旁边没有控制台窗口,只有win表单图标:

正如我之前所描述的,当您尝试在没有人时写入控制台时,所有其他调用Console.WriteLine都不会影响您的控制台应用程序.这就是为什么你可以看到任何控制台消息,即使你在构造函数中执行断点.
我认为Ilya Ivanov的答案可能是最好的答案.不过也认为我的一个有趣的答案:
public class Program
{
static Program()
{
Console.WriteLine("line no 1");
Console.WriteLine("line no 2");
Console.WriteLine("line no 3");
Environment.Exit(0);
}
static void Main(string[] args)
{
Console.WriteLine("line no 2");
}
}
Run Code Online (Sandbox Code Playgroud)
让我们使用 AOP,并利用 PostSharp。您需要先下载并安装它,然后需要使用 NuGet 添加对它的引用。您必须安装它,因为它是编译器的挂钩。看,当您编译代码时,PostSharp 实际上根据您使用的挂钩将 IL 注入到输出中。
完成这两件事后,为 AOP 属性添加一个新类:
using PostSharp.Aspects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
[Serializable]
public class ConsoleAspect : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
base.OnEntry(args);
Console.WriteLine("line no 1");
}
public override void OnExit(MethodExecutionArgs args)
{
base.OnExit(args);
Console.WriteLine("line no 3");
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后Main像这样修改你的方法:
[ConsoleAspect]
static void Main(string[] args)
{
Console.WriteLine("line no 2");
}
Run Code Online (Sandbox Code Playgroud)