SourceYard製做源代碼包

title author date CreateTime categories
SourceYard 製做源代碼包
lindexi
2018-12-25 9:43:7 +0800
2018-12-09 09:41:57 +0800
 

本文帶你們走進SourceYard開發之旅 在項目開發中,將一個大的項目拆爲多個小項目解耦,減小模塊之間的耦合。由於若是將代碼放在一塊兒,即便有團隊的約束,但只要能寫出的代碼就會有小夥伴寫出,很快就發現各個模塊耦合的代碼不少。可是對一個項目的拆分會讓拆分出來的每個項目都編譯出一個 dll 增長運行文件的啓動時間。 在開發中,經常會用到不少工具類,這些小輪子不少的功能基本就只有一個類,如何對這些小輪子進行管理?經過複製代碼仍是經過 Nuget 管理?html

若是使用複製代碼的方式,很難知道從哪裏複製代碼,若是在不少項目都複製了代碼,發現原來的代碼存在一些蟲子,很難修改全部複製代碼的項目。經過傳統 Nuget 的方式能夠方便管理工具的更新,和引入工具,同時會將每一個小輪子打包成一個 dll 這樣會引入不少 dll 讓軟件啓動的速度和運行的速度下降。關於 dll 數量和啓動時間的測試請看 C# 程序集數量對軟件啓動性能的影響 介紹了程序集數量對軟件啓動性能的影響,運行的性能是在引用某個 dll 方法的時候須要加載這個 dll 下降速度。git

有小夥伴問,爲什麼不將全部的工具放在一個大的項目,這樣每次只須要更新大項目的 Nuget 就能夠,這樣就能夠解決引入dll的數量和管理小工具。程序員

雖然將不少的工具放在一個程序集作一個 Nuget 的方式看起來不錯,可是隻是在很小的項目同時不能維護過久,在我如今的團隊有一個庫,這個庫就是用來放小工具,可是在通過了一段時間,發現基本上全部小夥伴在不知道要將類放在哪一個地方的時候,就會放在這個程序集裏。同時由於全部工具都在一個程序集裏,全部小工具都在相互引用。在我想要修復某個小工具的功能的時候,發如今這個程序集內這個工具已經有 99 引用,其中還有很多地方依賴 bug 編程,這時維護這樣一個程序集的成功很是高,同時沒法組織小夥伴不斷將含義不明確的類放在這個程序集(這裏不是在討論代碼審查問題,在我如今的團隊是有明確的代碼審查,然而沒有人能說清這個程序集的功能),因此這就是爲何不建議全部小工具放在一個程序集的緣由。另外若是都將代碼放在一個程序集,用於分享也是比較難,有小夥伴向我要一些工具,假設我都放在一個程序集裏,那麼我只能經過拷貝代碼的方式給他,由於我不肯定工具程序集裏面是否有不能對外發布的內容,但若是是 SourceYard 的方法,做爲源代碼包能夠將小夥伴須要的工具發佈到 Nuget.org 請他去安裝。github

固然將工具放在一個工具程序集也不是沒有優勢,由於全部的工具都在一個程序集裏面,小夥伴能夠方便找到本身須要的類,而不是經過 Nuget 的方式去尋找安裝。同時若是有一個項目多個程序集須要相同的工具,能夠同時依賴工具程序集,減小建立出來的 dll 文件裏重複代碼。編程

解決上面的兩個問題的方法是經過 SourceYard 的方法,使用 SourceYard 不但能夠解決項目解耦建立了不少個項目讓不少個項目編譯出來的 dll 太多讓軟件啓動性能下降,同時解決小工具類太多的問題,還能夠解決代碼兼容的問題。api

控制檯項目

建立一個 dotnet core 項目進行開發,這裏建立一個 dotnet core 項目主要是由於建立出來的項目清真緩存

假設有一個需求是作一個工具,這個工具的功能是用戶輸入數字,轉換爲人民幣金額大寫,聽起來這個功能很簡單,固然在本文就不會詳細告訴你們這個工具的代碼。服務器

在我以前的博客C# 金額轉中文大寫已經有了代碼,能夠從碼雲複製 複製的代碼由於沒有命名空間,須要手動添加,因而如今就建立了一個項目,這個項目包含一個類。ide

使用 SourceYard 很簡單,只須要在 TheLib 項目管理 Nuget 安裝 SourceYard 就能夠函數

如今 SourceYard 還沒正式發佈,裏面還存在一些坑,可是對於這麼簡單的項目已經可使用。

若是對 SourceYard 感興趣,請在 github 關注

右擊 TheLib 的屬性,在打包的頁面勾選在版本中生成 Nuget 包,勾選以後從新編譯就能夠製做出 Nuget 包。可是請不要急,在打包頁面還有不少東西須要填寫,在廣州 .NET 微軟技術俱樂部12月份活動 的演示中,我使用了這個黑科技瞬間完成了全部屬性,小夥伴若是還沒學會這個黑科技就須要手動填寫內容了,其實只有做者、公司、說明是必要的,其餘的能夠不寫。

 

若是須要將 TheLib 修改成 dotnet framework 的項目,只須要右擊編輯 csproj 文件就能夠,在理解 C# 項目 csproj 文件格式的本質和編譯流程和廣州 .NET 微軟技術俱樂部12月份活動 呂毅都講了項目的格式,若是隻須要修改 dotnet framework 不須要了解那麼多,只須要在 TargetFramework 裏面修改成 net45 就完成

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net45</TargetFramework>
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="dotnetCampus.SourceYard" Version="0.1.7213-alpha">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
    </PackageReference>
  </ItemGroup>

</Project>

如今右擊項目從新編譯就能夠打出 Nuget 包,在使用新的項目格式,默認的 dotnet core 項目就是這麼簡單,具體請看VisualStudio 使用新項目格式快速打出 Nuget 包詳細寫了黑科技

在輸出的文件夾能夠找到打包的 Nuget 文件

文件能夠經過 Nuget 管理器 打開,這個文件能夠在應用商店找到

這裏兩個不一樣的文件,其餘是傳統的 Nuget 包,也就是 TheLib.1.0.2.nupkg 裏面包含 dll 請打開文件很快就能夠看到

源代碼的文件的格式也請小夥伴打開看一下,裏面沒有 dll 裏面是代碼,在安裝這個文件就會引用代碼,代碼會編譯在引用的項目。多個不一樣的源代碼包會編譯爲一個程序集。

雖然有 Nuget 文件可是還不知道這個文件能不能使用,建立兩個不一樣的項目用來用這兩個文件,由於剛纔已經修改項目爲 dotnet framework 的,就須要建立一個 dotnet framework 的項目

右擊項目管理 Nuget 引用本地的 Nuget 文件的文件夾,如我這裏的 Nuget 文件是在 D:\lindexi\SourceYard\bin\Debug 文件夾下,我就須要添加這樣的路徑,請看圖片

這裏的程序包源的名稱是能夠隨意給的,程序員最難的就是命名,好在有Whitman 這個工具能夠按下 ctrl+, 輸入第一個字符爲小寫的變量,按下 ctrl+shift+, 輸入第一個字符爲大寫的變量。如今這個工具已經從 dotnet framework 升級到 dotnet core 請看 將基於 .NET Framework 的 WPF 項目遷移到基於 .NET Core 3 - walterlv 關於 WPF 怎麼能夠在 dotnet core 運行,微軟已經將 WPF 的 dotnet core 開源,能夠在 github 找到

如今點擊本地的源,如剛纔命名爲 TacaluTawnenai 的源就能夠找到剛纔的兩個文件,如何選擇本地的源?請看下圖,點擊程序包源的下拉就能夠找到

剛纔建立的 dotnet framework 程序仍是比較不清真的,先進行卸載,而後編輯 csproj 文件,能夠看到這裏的文件內容很是多,這是很不清真的。從剛纔的 TheLib 文件裏面拷貝 csproj 文件到 AppUsingDll 項目裏,記得須要先去掉 SourceYard 的部分

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net45</TargetFramework>
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="dotnetCampus.SourceYard" Version="0.1.7213-alpha">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
    </PackageReference>
  </ItemGroup>

</Project>

將上面不須要的部分,也就是引用 SourceYard 包的部分和 GeneratePackageOnBuild 去掉,如今剩下的代碼不多

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net45</TargetFramework>
  </PropertyGroup>
</Project>

控制檯項目須要作很小的修改,經過右擊項目屬性,在界面選擇控制檯

若是此時進行編譯會看到編譯不經過,由於還須要刪除 AssemblyInfo.cs 文件的不少代碼,其實能夠直接刪除這個文件

在這個項目須要安裝 TheLib 庫,安裝的方式和安裝其餘的 Nuget 沒有不一樣,經過本地的文件夾安裝 Nuget 包和經過 Nuget 服務器安裝沒有不一樣,若是須要本身搭建 Nuget 服務器也是十分簡單,請看經過ProGet搭建一個內部的Nuget服務器 - 張善友 - 博客園,我就幫小夥伴在10分鐘內搭建 Nuget 服務器

安裝以後添加一點代碼測試一下可否使用

            var money = new Money(12312);
            Console.WriteLine(money.ToCapital());
            Console.ReadLine();

這時運行一下,能夠看到成功運行了。

再建立一個項目,這個項目嘗試使用 dotnet core 的項目

右擊項目管理 Nuget 安裝源代碼包,而後在主函數添加相同的測試代碼

        static void Main(string[] args)
        {
            var money = new Money(12312);
            Console.WriteLine(money.ToCapital());
            Console.ReadLine();
        }

如今嘗試運行,能夠看到和剛纔的 dotnet framework 控制檯輸出相同

可是有一點不相同的是,打開兩個項目的輸出文件夾,能夠看到 dotnet framework 項目引用的是 dll 的方式,輸出的文件夾有一個dll和一個exe 在 dotnet core 項目的輸出文件夾只有一個 dll 由於默認的 dotnet core 輸出的是 dll 源代碼就放在相同的 dll 裏

這時就能夠看到 SourceYard 的好處,經過 SourceYard 能夠將源代碼做爲 Nuget 包,這樣不但減小 dll 的數量,同時作到源代碼的兼容。在以前,不管是PCL仍是多項目方式的 Nuget 包管理多個不一樣平臺的兼容難度比較大,可是經過 SourceYard 只要源代碼能夠兼容就能夠安裝。在本文的控制檯的使用的庫是 dotnet framework 4.5 可是控制檯項目使用的是 dotnet core 2.1 的,這樣均可以使用。

WPF 程序

若是小夥伴以爲控制檯仍是太簡單了,能夠嘗試使用桌面WPF程序,此時 WinForms 程序也是適合的。

建立一個簡單的 WPF 庫,注意建立以後須要修改代碼,修改項目格式爲 VisualStudio 2017 格式

在開始編輯以前,先建立一個用戶控件,這裏叫 InterestingControl 一個有趣的控件,同時刪除 Properties 文件夾的全部文件

相對來講,作 WPF 的庫使用新項目格式要求對新的格式比較熟悉,因此請直接卸載項目,編輯一下項目文件,填入下面的代碼

<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
  <PropertyGroup>
    <LanguageTargets>$(MSBuildToolsPath)\Microsoft.CSharp.targets</LanguageTargets>
    <TargetFrameworks>net45;</TargetFrameworks>
    <OutputType>Library</OutputType>
    <RootNamespace>WpfUI</RootNamespace>
    <AssemblyName>WpfUI</AssemblyName>
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
  </PropertyGroup>
  <PropertyGroup>
    <DefineConstants>$(DefineConstants);WPF</DefineConstants>
  </PropertyGroup>
 
  <ItemGroup>
    <Compile Update="**\*.xaml.cs">
      <DependentUpon>%(Filename)</DependentUpon>
    </Compile>
    <Page Include="**\*.xaml">
      <SubType>Designer</SubType>
      <Generator>MSBuild:Compile</Generator>
    </Page>

    <Resource Include="**\*.png" />
    <Resource Include="**\*.jpg" />
    <Resource Include="**\*.cur" />
    <Resource Include="**\*.ps" />
    <None Include="**\*.fx" />
    <None Include="**\*.md" />
    <None Include="**\*.ruleset" />
  </ItemGroup>
 
  <ItemGroup>
    <Compile Remove="obj\**" />
    <EmbeddedResource Remove="obj\**" />
    <None Remove="obj\**" />
    <Page Remove="obj\**" />
    <Resource Remove="obj\**" />
  </ItemGroup>
 
  <ItemGroup>
    <PackageReference Include="dotnetCampus.SourceYard" Version="0.1.7213-alpha">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
    </PackageReference>
  </ItemGroup>
 
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Xaml" />
    <Reference Include="WindowsBase" />
    <Reference Include="PresentationCore" />
    <Reference Include="PresentationFramework" />
  </ItemGroup>
 
  <ItemGroup>
    <Compile Update="InterestingControl.xaml.cs">
      <SubType>Code</SubType>
    </Compile>
  </ItemGroup>
 
  <ItemGroup>
    <Folder Include="Properties\" />
  </ItemGroup>
 
  <ItemGroup>
    <None Update="InterestingControl.xaml">
      <Generator>MSBuild:Compile</Generator>
    </None>
  </ItemGroup>
</Project>

請根據實際的項目更改 AssemblyName 的值

製做源代碼包的方式和控制檯的相同,只須要在 Nuget 安裝 SourceYard 就能夠,一樣打開屬性,和控制檯同樣

如今右擊從新編譯,就能夠在輸出文件夾找到輸出的兩個 Nuget 包

再建立一個 WPF 程序,經過設置本地的 Nuget 包的文件夾,安裝源代碼包,而後在界面使用剛纔的用戶控件,運行就能夠發現成功使用了用戶控件

打開 WPF 程序的輸出文件夾,能夠發現這個文件夾裏面只有一個 exe 源代碼已經放在 exe 裏

調試

在將項目製做 Nuget 包的時候,就有小夥伴吐槽在開發的時候,若是使用 Nuget 安裝,很難進行調試,很難在 dll 裏面添加斷點,同時在調試的時候修改代碼

可是在使用 SourceYard 調試的時候,安裝 Nuget 的庫和調試本地的引用的代碼是徹底同樣的,就使用上面的控制檯調試

例如須要不管用戶輸出的是什麼返回的都是 林德熙是逗比

細心的小夥伴會發現安裝 SourceYard 以後,在項目會出現一個文件夾是 SourceProject 裏面就有一個文件 TheLib.Source.SourceProject.props 打開這個文件能夠看到下面的內容

<?xml version="1.0" encoding="utf-8"?>
<Project>

  <!--這個文件由代碼建立,不建議刪除這個文件-->

  <!--取消下面的註釋,而且修改路徑爲本身對應的 TheLib.Source 文件夾的目錄,能夠經過修改源代碼測試-->

  <!--<PropertyGroup Condition=" !$(DefineConstants.Contains('TheLibSOURCE_REFERENCE')) ">
    <DefineConstants>$(DefineConstants);TheLibSOURCE_REFERENCE</DefineConstants>
  </PropertyGroup>-->
  
  <!--修改路徑爲本身的源代碼文件夾-->
  <!--  <PropertyGroup>
    <TheLibSourceFolder>c:\lindexi\source\ 這是一個示例文件夾,請將這個替換爲本身的源代碼包文件夾</TheLibSourceFolder>
  </PropertyGroup>  -->


</Project>

這個文件裏面有一些代碼暫時沒法使用,須要先作設置,首先設置 TheLibSourceFolder 這裏表示源代碼包的原始項目的文件夾,如 TheLib 的文件夾是 C:\lindexi\SourceYard\TheLib 請當心設置路徑

而後取消除了中文的註釋,請看代碼

<?xml version="1.0" encoding="utf-8"?>
<Project>

  <!--這個文件由代碼建立,不建議刪除這個文件-->

  <!--取消下面的註釋,而且修改路徑爲本身對應的 TheLib.Source 文件夾的目錄,能夠經過修改源代碼測試-->

  <PropertyGroup Condition=" !$(DefineConstants.Contains('TheLibSOURCE_REFERENCE')) ">
    <DefineConstants>$(DefineConstants);TheLibSOURCE_REFERENCE</DefineConstants>
  </PropertyGroup>

  <!--修改路徑爲本身的源代碼文件夾-->
  <PropertyGroup>
    <TheLibSourceFolder>C:\lindexi\SourceYard\TheLib</TheLibSourceFolder>
  </PropertyGroup>


</Project>

此時經過 ctrl+點擊的方式能夠進入 Money 文件,這時能夠進行調試

此時在這個函數下面返回林德熙是逗比

按 F5 運行,能夠看到輸出的是 林德熙是逗比 也就是源代碼已經修改

打開 TheLib 的 Money.cs 文件能夠發現裏面的文件也同時被修改,也就是這個文件被兩個項目引用,經過這個方法就和將項目引用的方式那樣調試解決 dll 難以斷點和修改代碼

若是不設置 TheLibSourceFolder 路徑,也是能夠調試文件,一樣也能夠在調試的時候修改代碼,可是這時的代碼是沒法上傳的,也就是隻能在本地的緩存使用,在清空緩存以後,對代碼的修改將會找不到

由於 SourceYard 還在開發過程,代碼開放在 github 歡迎小夥伴貢獻