2018-12-25-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# 金额转中文大写已经有了代码,能够从码云复制 复制的代码由于没有命名空间,须要手动添加,因而如今就建立了一个项目,这个项目包含一个类。函数

使用 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 欢迎小伙伴贡献