之前一直用FineUICore做框架,系统登录,人员 字典 菜单 权限管理啥的,公司也一直在用,但是框架分散在各项目不好维护,所以个给组件化了,在项目中引用,并且打包放在了公司的服务器上,这里做个积累
之前一直不知道MVC(带Controller)的项目怎么像dll一样给另一个项目引用并加载视图,直到学习了从零开始实现ASP.NET Core MVC的插件式开发
只要跟着文章一点点试就能出来,这里要注意使用框架项目和实例项目要使用同样的包引用和.net版本否则编译不了
最后像这样 (HD_System 就是编译好的组件)
var assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + "HD_System.Web.dll"); services.AddControllers(option => { option.Filters.Add(typeof(GlobalExceptionsFilter)); }).AddNewtonsoftJson(opt => { //忽略循环引用 opt.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; //不改变字段大小 opt.SerializerSettings.ContractResolver = new DefaultContractResolver(); //不改变字段大小 //opt.SerializerSettings.ContractResolver = new CustomContractResolver(); }) .AddApplicationPart(assembly);
这里带来的问题是 每次框架项目(HDSystem)修改都要复制dll到各实例项目,要复制一堆,前期我写了个 bat 的脚本,在项目编译前复制文件到项目的 bin 目录下,但是每个项目都在本地写脚本对于多人异地开发带来不便,这里就用到 Nuget 包管理
;
由于只供本地使用,所以搭建本地的Nuget服务器 BaGet ,官网了搭建流程非常详细,这里不做说明;把发布的包下下来,摁到服务器上发布就行了,这个项目也是用.net写的,直接 dotnet BaGet.dll 就行了;
然后再VS2022中配置私服地址,可以看这里 基于 BaGet 搭建 Nuget 服务器
在Baget的配置(appsettings.json)中,我只修改了一个配置 "AllowPackageOverwrites": true
,允许包覆盖 因为可能上传的版本老是修改 懒的改版本号;
我还学习研究了官方的 Nuget命令 ;看的不老懂的
这里我还是使用了git钩子,由于源码传到Linux服务器(CentOS7),这里上传后直接触发脚本打包并发布到Nuget私服
通过脚本进行项目的打包 即 dotnet pack
命令,注意要 cd 到项目目录下,如:
echo '-------------开始打包---------------' #打包后地址 PackagePath='/home/HD_System/NugetPackage' #运行打包 cd /home/HD_System/HD_System/HD.Commons #dotnet pack 项目文件 --output 地址 dotnet pack HD.Commons.csproj --output $PackagePath
最后推送到服务器
echo '-------------开始推送-------------' cd $PackagePath dotnet nuget push "*.nupkg" -s http://127.0.0.1:9090/v3/index.json --skip-duplicate
正常到这里项目就能拉到了,一安装就可以用了,然后问题就来了;
遇到的第一个问题是版本号,由于框架项目也是多一个项目(.csproj,比如 公共库 业务 UI扩展 Web项目)组成 ,互相引用,每个项目都单独发包了(解耦),这里要注意 底层项目的版本号变更,上层的也要变更,否则上层项目打包之后 会提示 找不到版本(他会找旧的库),
因为 dotnet pack
时如果当前项目的版本号没有更新,它是不重新编译的,只会把缓存直接拿出来告诉你打包完了,其实包没变,所以引用的还是旧版的基础包;
关于版本号,只要在vs中双击项目,直接修改就行了
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <Authors>没想好</Authors> <Title>HD_System 框架基础文件</Title> <Version>1.0.1.24</Version> </PropertyGroup> </Project>
微软官方的教程里 说 dotnet pack
不能打包Web项目,只能打包类库,但是我一开始就要解决的是 Web项目组件化 ,实例项目读取的是动态的 dll 文件 ,而不是引用该dll
var assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + "HD_System.Web.dll");
所以Web项目生成的dll文件,只作为静态文件就可以了,在实例项目运行时将文件复制到发布目录即可;同样 js css 图片文件(FineUI环境)也是静态文件,这些文件要复制到项目的wwwroot下,并且要保持路径;(这两个需求我测试70多个版本,终于成功了)
思路是原框架项目在服务编译发布(不是打包),得到 dll 和 wwwroot ;将静态文件 复制到一个空项目下,由该空项目执行打包,读取的配置文件是.nuspec
,执行的规则是.targets
首先新建 文件夹 WebNuspec,包含文件如下
build ∟--HD_System.Web.dll --静态dll ∟--HD_System.Web.targets --规则 ∟--wwwroot --静态文件 ∟--res... --js等 contentFiles ∟--any ∟--any ∟--wwwroot --静态文件 同上 ∟--res... HD_System.Web.nuspec --配置 WebNuspec.csproj --空项目
HD_System.Web.nuspec 文件内容
<?xml version="1.0" encoding="utf-8"?> <package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"> <metadata> <id>HD_System.Web</id> <version>1.0.1.24</version> <contentFiles> <files include="*.dll" buildAction="Build"></files> <files include="**/*" buildAction="None" /> <files include="HD_System.Web.targets" buildAction="Build"></files> </contentFiles> </metadata> </package> ~
WebNuspec.csproj 文件内容
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net7.0</TargetFramework> <NoBuild>true</NoBuild> <IncludeBuildOutput>false</IncludeBuildOutput> <NuspecFile>PATH_TO_NUSPEC_FILE</NuspecFile> </PropertyGroup> </Project>
HD_System.Web.targets 文件内容
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <!-- 如果是dll 复制到发布文件 --> <None Include="$(MSBuildThisFileDirectory)\*.dll"> <Link>%(Filename)%(Extension)</Link> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup> <!-- 这里执行的是wwwroot的复制 --> <Target Name="CopyScriptsToProject" BeforeTargets="PrepareForBuild"> <ItemGroup> <SourceScriptFiles Include="$(MSBuildThisFileDirectory)\wwwroot\**\*.*" /> </ItemGroup> <Copy SourceFiles="@(SourceScriptFiles)" DestinationFiles="$(ProjectDir)\wwwroot\%(RecursiveDir)%(Filename)%(Extension)"/> </Target> </Project>
打包和复制目录命令
dotnet publish HD_System.Web.csproj -r linux-x64 -p:PublishDir=bin/publish #复制目录 cp -r 略/wwwroot/* 略/WebNuspec/contentFiles/any/any/wwwroot #复制文件 cp 略/bin/publish/HD_System.Web.dll 略/WebNuspec/build/HD_System.Web.dll
发布时 cd 到这个目录下,还是执行 dotnet pack
cd /home/HD_System/HD_System/WebNuspec #执行空项目的打包 但是配置文件读取 HD_System.Web.nuspec dotnet pack WebNuspec.csproj -p:NuspecFile=HD_System.Web.nuspec --output $PackagePath
问题又来了,使用-p:NuspecFile
命令后 版本放不上,读取的是 HD_System.Web.nuspec 文件中的版本号,所以要读取原始项目的版本号将 HD_System.Web.nuspec 文件中的版本号替换,说白就是读取xml,在改变一个xml项,代码如下
#得到版本号 cd /home/HD_System/HD_System/HD.System.Web/ TARGET_XML_FLIE=HD_System.Web.csproj #原项目文件 读取Version字段 Version=`grep -E -o -e '<Version>.+</Version>' $TARGET_XML_FLIE | sed 's/<Version>//g'|sed 's/<\/Version>//g'` echo $Version #修改版本号 cd /home/HD_System/HD_System/WebNuspec function change(){ if [ $# -eq 3 ]; then sed -i 's/<'"$1"\>'.*</<'"$1"'\>'"$2"'</g' $3 else echo error fi } change version $Version HD_System.Web.nuspec
Nuget打包,可以把同样是Nuget安装的文件一块都打包了,实例项目不用引用直接就能还原上,但是对于dll文件的打包,比如FineUICore.dll,在框架项目中引用,在实例项目中我希望自动引用;
在 HD.UIControl.csproj 中加入这句就可以了 (该功能由BingAI提供)
<!--包含在项目中--> <ItemGroup> <Reference Include="FineUICore"> <HintPath>bin\FineUICore.dll</HintPath> </Reference> </ItemGroup> <!--输出到打包目录--> <ItemGroup> <None Include="bin\FineUICore.dll" Pack="true" PackagePath="lib\net7.0" /> <None Include="bin\FineUICore.xml" Pack="true" PackagePath="lib\net7.0" /> </ItemGroup>
本地nuget缓存, 删除缓存版本 C:\Users\shiyu.nuget\packages
libstdc++ 找不到
yum install glibc-static libstdc++-static -y
至此所有问题解决,实现了源码和静态文件的包管理,
本文作者:没想好
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!