c#属性高于main
Posted
技术标签:
【中文标题】c#属性高于main【英文标题】:c# attribute over main 【发布时间】:2013-04-13 10:53:46 【问题描述】:有人问我如何打印
line no 1
line no 2
line no 3
不改变读取的主要方法
static void Main(string[] args)
Console.WriteLine("line no 2");
现在一种方法是为控制台应用程序设置多个入口点。但是我尝试了另一种方法,如下所示:
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");
当我在每个 WriteLine 上应用断点时,我可以看到该方法有效,但是在控制台上没有反映出来。
只是好奇。
【问题讨论】:
Without changing a main method which reads
...真的吗?!?
@MichaelPerrenoud:我很确定这是一个需要一些聪明思考的练习。事实上,我真的认为这很有趣。
@ArnoSluismans,没关系。这真的很简单,真的很奇怪。但是感谢您引导我走上正确的道路,看看我的回答。
下面的解决方案都很有帮助,但我很好奇为什么尽管命中了断点,正如预期的那样,属性技术不起作用。
【参考方案1】:
您的问题可以分解为钩子的搜索,这些钩子在控制台应用程序的Main
方法执行之前和之后触发。
第一个钩子是一个Program
静态构造函数,它是guarantee 在Program
类中执行之前 Main
方法。
Second 是 AppDomain
的事件 ProcessExit,“在默认应用程序域的父进程退出时发生”。您可以使用静态构造函数订阅此事件。
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");
打印:
line no 1
line no 2
line no 3
下一部分会很长。我将尝试在您的问题中解释SomeAttribute
的问题。
首先,考虑这个 *** 问题以准确了解when custom attributes constructors are executed。这并不像乍一看那么简单。
我们已经知道,自定义属性的 ctor 只会在您通过反射访问它时执行。因此,在您的示例中,简单的程序执行不会触发属性构造函数。但是,当您将SomeAttribute
应用于Main
方法时,为什么会出现断点?事实证明,Visual Studio 使用反射来找出主要方法并将调试器附加到您的应用程序。但此时没有控制台窗口。所以声明Console.WriteLine
是无用的并且产生效果。此外,它似乎阻止了控制台输出的所有下一条语句。
所以接下来的代码会产生不同的结果,这取决于你是否使用 VS 调试器运行它:
class Program
[MyAttribute]
static void Main()
class MyAttribute : Attribute
public MyAttribute()
MessageBox.Show("MyAttribute ctor");
如果你在没有调试器的情况下运行它(在 VS 默认配置中为 Ctrl + F5),你会看到,该程序终止并且没有窗口出现。当您使用调试器 (F5) 执行它时,您会看到
VS旁边没有控制台窗口,只有win表单图标:
正如我之前所描述的,当您在没有人的情况下尝试写入控制台时,对Console.WriteLine
的所有其他调用都不会影响您的控制台应用程序。这就是为什么您可以看到任何控制台消息的原因,即使您在构造函数中执行断点也是如此。
【讨论】:
+1 为答案,但我试图弄清楚为什么我的解决方案不起作用。 @user2277247 我更新了我的答案,解释了你观察到的行为【参考方案2】:我认为Ilya Ivanov's answer 可能是最好的。但是,我的答案也很有趣:
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");
【讨论】:
+1 开箱即用。无需执行Main
方法,问题陈述中的漂亮角落案例。【参考方案3】:
让我们使用 AOP,并利用 PostSharp。您将需要download and install it first,然后您需要使用 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");
然后像这样修改您的Main
方法:
[ConsoleAspect]
static void Main(string[] args)
Console.WriteLine("line no 2");
【讨论】:
以上是关于c#属性高于main的主要内容,如果未能解决你的问题,请参考以下文章
在c#中怎么能在一个窗口中设置另一个窗口控件的属性?急急急!!!