dotnet 读 WPF 源代码笔记 默认的 Main 函数是在哪创建的

在WPF项目中,Main函数位于App.g.cs,由编译过程中的代码生成逻辑创建。本文详细介绍了从App.xaml识别为ApplicationDefinition开始,如何通过GenerateAppEntryPoint、MarkupCompilePass2等步骤在构建过程中生成App.g.cs中的Main函数,包括SplashScreen和App对象的创建。整个过程在dotnet/wpf开源仓库中可查看。
摘要由CSDN通过智能技术生成

在使用默认的 WPF 项目开发的时候,咱是不需要自己编写 Main 函数的,在 WPF 中的 Main 函数是存放在 App.g.cs 里面,看起来这个 Main 函数是生成的函数,本文将介绍在 WPF 框架中是如何创建这个入口函数

阅读本文你将了解 WPF 框架中,默认在 App.g.cs 生成入口 Main 函数的详细过程。阅读本文之前,你需要了解一些编译过程的知识以及代码生成的知识

默认的 Application 继承类命名是 App.xaml 如果在你的项目中,依然使用默认的命名,那么在 .NET 5 的 SDK 下,将会自动加上以下默认的代码

    <ApplicationDefinition Include="App.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </ApplicationDefinition>

上面代码是将 App.xaml 识别作为 ApplicationDefinition 的特殊内容,这个内容将被作为创建入口函数的出发点文件。也就是 App.g.cs 文件里面存放入口函数就由此决定

src\Microsoft.DotNet.Wpf\src\PresentationBuildTasks\MS\Internal\MarkupCompiler\MarkupCompiler.cs 文件里面的 GenerateAppEntryPoint 函数,如此函数命名所示,这就是创建应用入口点的方法,大概逻辑如下

        private void GenerateAppEntryPoint()
        {
            if (ApplicationFile.Length > 0)
            {

                // [STAThread]
                // public static void Main ()
                //
                CodeMemberMethod cmmMain = GenerateEntryPointMethod();

                if (cmmMain != null)
                {
                    //   SplashScreen splashScreen = new SplashScreen("SplashScreen.png");
                    //
                    CodeVariableReferenceExpression cvreSplashScreen = null;
                    if (!string.IsNullOrEmpty(_splashImage) && !HostInBrowser)
                    {
                        cvreSplashScreen = GenerateSplashScreenInstance(cmmMain);
                    }

                    //   MyApplication app = new MyApplication();
                    //
                    CodeVariableReferenceExpression cvreApp = GenerateAppInstance(cmmMain);

                    if (_ccRoot.InitializeComponentFn != null)
                    {
                        //   app.InitializeComponent();
                        //
                        CodeMethodInvokeExpression cmieIT = new CodeMethodInvokeExpression();
                        cmieIT.Method = new CodeMethodReferenceExpression(cvreApp, INITIALIZE_COMPONENT);
                        cmmMain.Statements.Add(new CodeExpressionStatement(cmieIT));
                    }

                    if (!HostInBrowser)
                    {
                        //   app.Run();
                        //
                        CodeMethodReferenceExpression cmreRun = new CodeMethodReferenceExpression(cvreApp, "Run");
                        CodeMethodInvokeExpression cmieRun = new CodeMethodInvokeExpression();
                        cmieRun.Method = cmreRun;

                        CodeStatement csRun = new CodeExpressionStatement(cmieRun);
                        cmmMain.Statements.Add(csRun);
                    }

                    _ccRoot.CodeClass.Members.Add(cmmMain);
                }
            }
        }

在 WPF 中不是拼接字符串的方式完成代码生成的,而是需要用上代码生成逻辑进行生成。在上面代码中有各个注释来告诉大家生成代码的作用,阅读方便

调用链关系上,通过 Roslyn 如何了解某个项目在 msbuild 中所有用到的属性以及构建过程 的方法,可以看到在构建过程中,将会先使用 UsingTask 加载 MarkupCompilePass2 任务

  <UsingTask TaskName="Microsoft.Build.Tasks.Windows.MarkupCompilePass2" A
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值