Maui的學習之路(二) -- 設置
上一篇我們做了Maui
的基本介紹,理論上這一篇應該會創建第一個Maui的應用,以便對此進行詳細的評估,并逐步深入。
如果你需要進行Maui
首個應用的創建,那么歡迎訪問.NET MAUI 創建移動應用—Get Start (qq.com),以及MAUI與Blazor共享一套UI,媲美Flutter,實現Windows、macOS、Android、iOS、Web通用UI (qq.com),本文的重點不是創建Maui的應用而是如何更好的配置Maui
的工程。
解決煩人的“obj”
長久以來都有一個問題深深得困擾著我們,每當c#
程序編譯后,總會在項目文件夾下生成“obj”目錄,非常刺眼,一旦提交git
我們需要進行逐個排除(如果項目很多會生不如死)這讓人非常惱火。那么我們能不能把他移走?
在完成以下設置之前,請跟我做如下的事情:
創建一個
c++
工程(我們并非是要進行c++程序開發而是他會對我們后續的學習產生非常積極的作用)
(這里我創建了一個C++ Console工程)
創建一個
xml
文件,把他重命名為Directory.build.props
(這個名稱隨意,只是喜歡這么叫)



雙擊
Directory.build.props
文件打開并編輯,刪除xml中所有內容,在該文件中添加如下設置
<Project><PropertyGroup><BaseIntermediateOutputPath>$(MSBuildThisFileDirectory).vs\$(SolutionName)\Intermediate\$(MSBuildProjectName)\</BaseIntermediateOutputPath></PropertyGroup>
</Project>
這里我不會介紹BaseIntermediateOutputPath這個設置字段的用意,如果你需要知道請訪問:常用的 MSBuild 項目屬性 - MSBuild | Microsoft Docs[1](如果你是用的是vs2022 for mac
,那么很抱歉的告訴你他不支持這個屬性,我在官方的issue
翻閱過這個bug早在vs2019 for mac
就存在,只不過微軟視而不見),所以為了避免尷尬的事情發生,我們需要加上一個條件判定,這個條件就是當操作系統是windows
時這個設置項才生效
<!--這個屬性可以讓你跟obj?say?goodbye--><PropertyGroup?Condition="$([MSBuild]::IsOSPlatform('windows'))"><BaseIntermediateOutputPath>$(MSBuildThisFileDirectory).vs\$(SolutionName)\Intermediate\$(MSBuildProjectName)\</BaseIntermediateOutputPath></PropertyGroup>
在這里我不得不說微軟vs
團隊是真的強大,你只需要安裝vs
就能在不同的平臺打開同一份代碼,而不需要做其他的編譯設置
我們是一家人
當一個解決方案(Solution)存在多個項目時(csproj),我們一定希望所有項目生成的dll
或者exe
以及配置文件都統統編譯生成到一個固定的地方,通常我們都會手動設置編譯生成路徑,這個方式極不推薦因為你所做的選擇總是一個不可靠的路徑(如果這是一個團隊合作的項目),我們只需要做如下一點點改變(該設置仍然是在Directory.build.props
中進行添加)
<PropertyGroup><!--這個屬性可以讓你規劃統一生成路徑--><OutputPath>$(MSBuildThisFileDirectory)Binary\</OutputPath></PropertyGroup>
讓他成為全部
我們常常有這樣的思考,能不能在一個地方配置,所有工程都能有改變,比如Nullable的啟用,比如C#的語言版本等等,那么只需要對Directory.build.props
增加如下配置
<PropertyGroup><!--這個屬性可以讓你規劃統一生成路徑--><OutputPath>$(MSBuildThisFileDirectory)Binary\</OutputPath><LangVersion>latest</LangVersion><Nullable>enable</Nullable><ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
不能沒有你
你是否有這樣的困惑,當我的解決方案(Solution)下的所有項目(csproj)都需要用到同一個package
時,我能否只要做一次包的引用行為?接下來請跟我一起操作:
創建一個
xml
(這已經很熟悉了),將他改名為Directory.build.targets
(我喜歡這個名字)


將
Directory.build.targets
中的內容修改為:
<Project><!--這樣的設計可以讓你當前解決方案下的所有項目都能獲取到package--><ItemGroup><PackageReference?Include="Newtonsoft.Json"?Version="13.0.1"?/></ItemGroup>
</Project>
讓他變得主動
完成上述設置你已經成為一個解決方案管理高手了,但是這還不夠,我們都知道.net6
或者是c#10
引入了文件級別的命名空間(File-scoped
)你只需要寫一個 namespace xxx
,更少的大括號讓你的代碼看起來更加簡潔,很可惜如果你不做任何改變,那么他永遠不會那么主動,你創建的默認class
他一定長這樣:
namespace?MauiLib1
{internal?class?Class2{}
}
請跟我完成以下操作,他會變得更聽話:
創建一個editorconfig


雙擊.editorconfig,開啟File scped配置(如果你打開的不是設置界面而是直接打開的文本,請不用擔心,在下一次重啟后再完成后續的設置即可)

至此你就完成了部分高效設置,關閉vs
,重新打開解決方案,上述所有設置才會生效,別忘了刪除已經產生的編譯垃圾,如以下這些:

此時你創建的新的class
,他變成了這樣:
namespace?MauiLib1;
internal?class?Class3
{
}
重新編譯解決方案,你的所有dll和exe都已經生成到binary下面了,每一個csproj目錄下都相當干凈了(注意以上設置對c++工程無效,c++工程需要單獨配置,這里不做介紹。
別忘了他
完成上述設置,我們剛剛創建的c++
工程似乎都沒有起到任何作用,沒錯c++
工程只是給你看看的(我就是玩兒你),接下來我們需要探討的是,這些你是怎么知道的(如圖)

其實這些是vs
的一些內置宏定義,我們在c#
中無法得知為什么有這些宏,此時我們需要用到c++
項目




在這里你可以看到這些形形色色的設置字段以及對應宏所顯示的值了,這個宏是屬于vs的,所以c#工程也有效
給得實在太多了
接下來我們會進行一些Maui
的深層設置探討,在Windows
上,總是默認給我編譯出android
、ios
、maccatalyst
,太多了我根本不需要,那么可以修改TargetFrameworks
(比如像這樣)

注意:一旦修改了這項,也就意味著你再也不能夠選擇其他平臺查看代碼是否正確(代碼可靠性將得不到保證)(去掉其他平臺編譯設置最直觀的表象就是編譯變得異常的快)
讓她變得忠誠
當我生成Window
的應用時,我們要引用一個Window
平臺相關的package
,比如我們很熟悉的Pinvoke.User32
,很明顯這個庫只適合Windows
平臺,其他平臺引用過去雖然不會造成編譯錯誤,但是在打包文件內勢必會有這個一個不相關的dll
(也許沒有我沒測試過,我猜他有),這是我們不希望看到的,所以我們要這樣:
<!--這是一個專屬于Windows的設定,讓他成為Windows忠誠的伴侶-->
<ItemGroup?Condition="$(TargetFramework.Contains('-windows'))"><!--?Required?-?WinUI?does?not?yet?have?buildTransitive?for?everything?--><PackageReference?Include="PInvoke.User32"?Version="0.7.104"?/>
</ItemGroup>
他們需要隔離
在編寫代碼時,我們通常會遇到我的部分代碼是適用于Windows
的而不適用于其他平臺,此時你可以使用編譯宏命令 #if #elif #else #endif
等
public?static?MauiApp?CreateMauiApp()
{var?builder?=?MauiApp.CreateBuilder();builder.UseMauiApp<App>().ConfigureFonts(fonts?=>{fonts.AddFont("OpenSans-Regular.ttf",?"OpenSansRegular");fonts.AddFont("OpenSans-Semibold.ttf",?"OpenSansSemibold");});#if?WINDOWSstring??name?=?"Windows";
#elif?MACCATALYSTstring??name?=?"Mac";
#elsestring??name?=?"Mobile";
#endifreturn?builder.Build();
}
讓他做回自己
我們很期待使用Maui
編寫的Windows
應用雙擊exe
就能夠直接運行(這在以前是個奢望),現在你只需要修改兩項設置就可以做到(在主程序的工程文件csproj
),增加如下兩個配置(使用該配置后就不再支持anycpu
編譯,所以我們做一個條件編譯):
<!--這個方案可以讓你的Maui在Windows下生成的exe做回自己-->
<PropertyGroup?Condition="'$(Platform)'?!=?'AnyCPU'?And?$(TargetFramework.Contains('-windows'))"><!--?Unpack?:?SelfContainedDeployment?for?winui3?--><WindowsPackageType>None</WindowsPackageType><WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
</PropertyGroup>
多編譯平臺配置
在上一項改動中,因為需要實現exe
直接運行,增加的設置在anycpu
編譯環境下是完全不支持的,所以你需要配置多平臺編譯方案(比如x64
x86
ARM64
等),配置方法如下:
點開
Configuration Manager
新增 X64等平臺編譯

綜上,我們完成了解決方案(Solution)以及項目(csproj)中的絕大多數設置,做好這些設置會讓你一部分工作變得得心應手。
以上設置都已上傳github[2]
參考資料
[1]
常用的 MSBuild 項目屬性 - MSBuild | Microsoft Docs: https://docs.microsoft.com/zh-cn/visualstudio/msbuild/common-msbuild-project-properties?view=vs-2022
[2]github: https://github.com/WPFDevelopersOrg/Demo