2018-12-6-Roslyn-如何基于-Microsoft.NET.Sdk-制作源代码包
title | author | date | CreateTime | categories |
---|---|---|---|---|
Roslyn 如何基于 Microsoft.NET.Sdk 制作源代码包
|
lindexi
|
2018-12-06 16:20:55 +0800
|
2018-07-11 10:35:34 +0800
|
Roslyn MSBuild 编译器
|
本文告诉大家如何做源代码包,源代码包的意思是安装的包不是安装dll的方式,而是使用源代码的方式。也就是最后是编译包的源代码而不是添加dll,这个方式是解决想要把项目分小,功能分细,但是不希望项目有很多的 dll,因为如果项目有很多 dll 会让软件打开的时间比较长
先来告诉大家做这个包的目的,如果是使用分开很多项目,一个项目会创建一个 dll ,在客户端的软件,用户很希望软件点击就打开。但是如果 dll 多了,读取dll文件的时间,加上加载 dll 的时间就会很长,这时用户就需要等待软件启动的时间就比较长。
但是从软件开发的功能,不同的功能应该使用不同的项目,这样才可以尽可能复用代码。为了让项目可以分细,而且减少创建的 dll 库,就需要使用本文的技术。
使用源代码的项目而不是引用 dll 的方法实际上在 Chrome 就是这样做,谷歌的开发就是有很多,大概有几百个项目,但是编译出来的 dll 只有一两个,所以他才有一点击就打开。
准备工作
在开始读本文之前,希望大家先了解一些概念,请看理解 C# 项目 csproj 文件格式的本质和编译流程 - walterlv,这一个文章告诉了大家一些基础,不然在看本文的时候会不知道为什么我需要这样写。
本文使用了修改编译,方法是 如何编写基于 Microsoft.NET.Sdk 的跨平台的 MSBuild Target - walterlv,从这个文章可以知道如何修改msbuild的编译
最简单的引用方法
将 .NET Core 项目打一个最简单的 NuGet 源码包,安装此包就像直接把源码放进项目一样 - walterlv
手工打包 Nuget 引用代码
如果看到了上面的博客,会发现实际上自己的需求还不是这么简单,如果需要真正做一个源码包,那么手动写 nuget 打包还是有必要的。
但是写一个手动打包的 Nuget 程序会占用本文太多的内容,所以我就不使用任何的代码进行打包,使用一步步告诉大家如何打包 nuget 的方法。
准备
首先需要有一个压缩工具,因为 nuget 的包 nupkg 就是一个压缩包
在应用商店搜索 nuget 可以安装 nuget package explorer ,或者点击安装
SublimeText 或 记事本,用来编辑文件
文件夹方式
一个可以解析的 nuget 包是需要包括指定的一些文件的,最主要就是.nuspec
文件,其他的文件都不是必要的
下面来告诉大家做一个空白的 nuget 包
创建空白的 nuget 包
首先创建一个空白文件,文件的后缀名是 nuspec ,文件名就是打包名
下面我创建 lindexi.nuspec
这个将会打出空白的 nuget 包
使用 SublimeText 打开 lindexi.nuspec 输入下面内容
<?xml version="1.0"?>
<package>
<metadata>
<id>lindexi</id>
<version>1.2.0</version>
<title>lindexi</title>
<authors>lindexi</authors>
<owners>林德熙;</owners>
<description>林德熙是逗比。</description>
</metadata>
</package>
标准的 nuget 包的 id 和 titile 、作者都是必须的,如果没有输入这些就无法打包
压缩一下,把后缀名修改为 nupkg 然后尝试使用 nuget package explorer 打开。
从图片可以看到压缩这个文件的压缩包的名字可以随便写,但是建议格式是 包的 id 加上 包的版本号,这样在垃圾 VisualStudio 才可以找到,不然总是会出现找不到包
现在尝试在 VisualStudio 设置包所在的路径,设置的方法我就不在这里告诉大家了,因为这时入门就需要知道的
在我设置了 nupkg 文件所在的文件夹之后,就可以在 VisualStudio 点击浏览,可以找到打出来的 nuget 包
现在需要在这个空白的 nuget 包添加多一些东西
添加 build 修改编译过程
刚才是不是觉得太简单了,下面就来告诉大家一些难度比较高的做法。
请严格按照本渣的方法来做,建议先自己走一次,发现成功了,再自己尝试修改,在本渣开始使用做源码包时,遇到了很多问题,所以我会在很多博客告诉大家。但是我不会在这个博客说道,这些知识很乱,而且和具体的 VisualStudio 版本有关,最近在给 MSBuild 修改,可能在大家用到就不会遇到这些坑。
如果大家觉得我这么辛苦,既要写文档又要给微软修vs那么就多给本渣点几个赞吧
现在把 nuget 的包的名字修改为清真的名字,现在的这个包是 lindexi.1.2.0.nupkg
这样就可以统一变量。
现在在 lindexi.nuspec
相同文件夹创建一个文件夹 build
注意大小写,现在的文件看起来就是这样
打开 build 文件夹,创建两个文件,需要注意这两个文件的文件名都需要保持和我一样,如果你修改为其他的文件名,没有开过光就无法使用
lindexi.props
lindexi.targets
现在还不需要在这两个文件里面写东西,先来写一下需要引用的源代码
引用的源代码
为了方便告诉大家源代码包是如何做的,这里就不需要创建一个工程来写源代码,只需要在 lindexi.nuspec
相同文件夹创建一个文件夹 src
这个文件夹可以不注意大小写。在这个文件夹创建一个文件 lindexi.cs
在里面写下面的代码
using System; namespace lindexi
{
class lindexi
{
public void Doubi()
{
Console.WriteLine("欢迎访问我的博客 blog.csdn.net/lindexi_gd");
}
}
}
如果你先把这个代码修改了也可以,这个代码的内容不需要和我一样
现在的文件结构是
├─build
├──lindexi.props
├──lindexi.targets
├─src
├──lindexi.cs
└─lindexi.nuspec
使用源代码
打开 build 文件夹的 lindexi.props 文件添加下面代码
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)..\src\lindexi.cs" ></Compile>
</ItemGroup>
</Project>
然后打开 lindexi.targets 添加下面代码
<?xml version="1.0" encoding="utf-8"?>
<Project>
</Project>
现在把整个文件夹压缩起来,然后修改压缩文件名 lindexi.1.2.nupkg
注意这个名字一定需要和我一样
现在就可以在 VisualStudio 安装刚才的包,看到这里就是已经告诉大家做的源码包的最简单方法
安装源码包
打开 VisualStudio 创建一个新的项目,在 nuget 设置刚才的 nuget 包所在文件夹,然后点击浏览就可以安装
安装之后可以看到 VisualStudio 多了一个文件
在主函数写下面代码,运行可以看到
var lindexi = new lindexi.lindexi();
lindexi.Doubi();
现在可以告诉大家源码包就这样做好了,使用这个方式就可以把自己的库作为源代码发给大家,这样即使很小的工具都可以做为一个nuget,而且安装也不需要担心 dll 太多软件启动比较慢。
但是可以看到这个方法都是需要自己对一个项目去写,如果想要自动去打包,请看 dotnet-campus/SourceYard: Add a NuGet package only for dll reference? By using dotnetCampus.SourceYard, you can pack a NuGet package with source code. By installing the new source code package, all source codes behaviors just like it is in your project.
如果使用上面的方法会发现自己的资源是找不到,包括 xaml 也是无法编译,在 xaml 里面引用资源也是找不到,不过这些问题我都会在 SourceYard 解决
原理
刚才大家可以看到我没有在 nuspec 添加引用,但是我可以使用这个源代码,原理就是新的 VisualStudio 格式可以在安装 Nuget 包自动寻找 build 文件夹的 包id.props
和 id.targets
文件,自动引用这两个文件
通过引用这两个文件可以发现文件里有下面代码
<Project>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)..\src\lindexi.cs" ></Compile>
</ItemGroup>
</Project>
从 理解 C# 项目 csproj 文件格式的本质和编译流程 - walterlv 可以知道,添加的集合就可以在编译引用
上面代码就是添加了lindexi.cs
文件作为编译,上面用到常量,请看项目文件中的已知属性(知道了这些,就不会随便在 csproj 中写死常量啦) - walterlv
所以在使用这个包就可以自动添加代码
自定义打包
虽然本金鱼在上面告诉大家这些变量的名字都需要保持和我说的一样,但是实际大家都想自定义
知道了原理是不是大家就可以写出其他代码,例如我的代码有两个文件 lindexi.cs
和 walterlv.cs
难道我需要使用两个代码
<Project>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)..\src\lindexi.cs" ></Compile>
<Compile Include="$(MSBuildThisFileDirectory)..\src\walterlv.cs" ></Compile>
</ItemGroup>
</Project>
实际上我只需要一句代码,请看下面
<Project>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)..\src\*.cs" ></Compile>
</ItemGroup>
</Project>
如果我还有文件夹,文件夹里有一些代码,我可以这样写
<Project>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)..\src\**\*.cs" ></Compile>
</ItemGroup>
</Project>
现在可以使用所有的 cs 文件了,但是存在的 xaml 文件还没有解决,而且我也不能让开发者去编辑引用的代码
虽然编译引用的代码是可以修改,但是这个修改会在升级版本之后就被去掉,也就是开发者以为自己修改代码解决一个问题,实际上在他升级库的时候会发现自己没有解决。因为这个代码引用的是 nuget 的文件,所以其他的开发者拉代码也会发现没有解决问题
所以这时需要设置 Visible="False"
,请看代码
<Project>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)..\src\**\*.cs" Visible="False"></Compile>
</ItemGroup>
</Project>
这样就可以让开发者在 VisualStudio 无法看到源代码,但是还是可以通过 Resharper 的方法跳转到源代码,如果他这么做了,我也没有办法
对于 xaml 资源,我需要在 props 文件使用下面代码才可以让 xaml 可以使用
<Compile Update="$(MSBuildThisFileDirectory)..\src\**\*.xaml.cs" Visible="False">
<DependentUpon>%(Filename)</DependentUpon>
</Compile>
<Page Include="$(MSBuildThisFileDirectory)..\src\**\*.xaml" Visible="False">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
对于资源文件,例如 WaterEffect.ps 因为资源是需要使用路径才可以使用,如果直接引用源代码会发现资源的路径是找不到,使用下面的代码就可以找到资源
<Resource Include="$(MSBuildThisFileDirectory)..\src\Effects\WaterEffect.ps" Link="Effects\WaterEffect.ps" Visible="False">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Resource>
需要注意,对于资源不能使用 *.ps
的方法,也就是通配是无法使用的,如果在Link
里使用了 *
那么就会发现无法编译
这个问题已经告诉了垃圾微软,不知道会不会在 VisualStudio 去修复。
资源问题坑了黄腾霄两天,坑了我一天,所以我才把这个问题在这里和大家说,如果大家使用了上面说道的工具,就不需要了解这么多,做源代码包很简单
解决 xaml 找不到方法问题
如果使用的是 WPF 程序,就需要额外添加一些代码,在 csproj 文件的开始和最后添加这样的代码
可以解决找不到xx类,或找不到 xx 方法或 CS1061
xx 未包含 xx 的定义,并且找不到可接受的第一个 xx 参数的可访问扩展方法
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<Import Condition="Exists('obj\xxx.csproj.nuget.g.props') " Project="obj\$(MSBuildProjectName).csproj.nuget.g.props" /> 其他代码 <Import Condition="Exists('obj\xxx.csproj.nuget.g.targets') " Project="obj\$(MSBuildProjectName).csproj.nuget.g.targets" />
</Project>
这里 xxx.csproj.nuget.g.targets 的 xxx 就是项目名,注意此时不能使用 $(MSBuildProjectName)
代替项目名,因为在编译过程是 xxx_一段我看不懂的字符_wpftmp.csproj
而不是直接的 xxx
项目
也就是 $(MSBuildProjectName).csproj.nuget.g.targets)
是不对的,因为 $(MSBuildProjectName)
是延迟计算,在 Import 还没有计算出来值
2018-12-6-Roslyn-如何基于-Microsoft.NET.Sdk-制作源代码包的更多相关文章
- 将 WPF、UWP 以及其他各种类型的旧 csproj 迁移成基于 Microsoft.NET.Sdk 的新 csproj
原文 将 WPF.UWP 以及其他各种类型的旧 csproj 迁移成基于 Microsoft.NET.Sdk 的新 csproj 写过 .NET Standard 类库或者 .NET Core 程序的 ...
- 迁移基于Microsoft.DirectX的AudioRecoder类到SharpDX上
最近迁移项目到x64上,要处理的东西还是蛮多的,所以我要在说一次,不到万不得已不要用COM组件,要用COM组件也得首先考虑不需要我们关心平台的做法,或者得有64位版本. 比如Office的COM组件调 ...
- 基于Microsoft Azure、ASP.NET Core和Docker的博客系统
欢迎阅读daxnet的新博客:一个基于Microsoft Azure.ASP.NET Core和Docker的博客系统 2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客 ...
- 基于Microsoft Graph打造自己的Timeline应用
原文链接:https://github.com/chenxizhang/office365dev/blob/e9b5a59cb827841d36692cc4ec52c11d43062e04/docs/ ...
- 2018.12.02 Socket编程之初识Socket
Socket编程主要分为TCP/UDP/SCTP三种,每一种都有各自的优点,所以会根据实际情况决定选用何种Socket,今天开始我将会逐步学习Socket编程,并将学习过程记录于此. 今天学习的是TC ...
- OPPO Developers Conference(2018.12.26)
时间:2018.12.26地点:北京国家会议中心
- Tencent Cloud Developers Conference(2018.12.15)
时间:2018.12.15地点:北京朝阳悠唐皇冠假日酒店
- 2018.12.1 Test
目录 2018.12.1 Test A 串string(思路) B 变量variable(最小割ISAP) C 取石子stone(思路 博弈) 考试代码 B C 2018.12.1 Test 题目为2 ...
- 「版本升级」MyEclipse CI 2018.12.0正式发布
新版本MyEclipse为WildFly 14新增一个新的服务器连接器,改进性能并新增一些Java 10修复程序.新版本为IDE做了几个核心修复,这是MyEclipse 2018一个更棒的升级. [M ...
随机推荐
- Java 虚拟机 - 2.3 HotSpot虚拟机对象
对象的创建 Step1 类加载检查 当发现一条new指令时,检查: 该指令的参数是否能在常量池中定位到一个类的符号引用: 并且检查这个符号引用代表的类是否已经被加载.解析和初始化过.如果没有,那必须先 ...
- 【JZOJ6388】小w的作业
description analysis 二分一个角度,首先假设该弧度角\(\theta \in[{\pi \over 2},\pi]\),要找的直线斜率\(k\in(-∞,\tan\theta]\) ...
- java 选择结构if
图1-1 if…else if…else语句的流程图 选择结构if语句与三元运算转换 三元运算符,它和if-else语句类似,语法如下: 判断条件 ? 表达式1 : 表达式2 三元运算符会得 ...
- day20 装饰器补充
Python之路,Day8 = Python基础8 装饰器from functools imoort wraps # 保留原函数所有信息,比如:用__doc__查看注释的时候,显示原来的注释def f ...
- thinkphp 三元运算
模板可以支持三元运算符,例如: {$status?'正常':'错误'} {$info['status']?$info['msg']:$info['error']} 注意:三元运算符中暂时不支持点语法. ...
- luoguP3414 SAC#1 - 组合数
题目背景 本题由世界上最蒟蒻最辣鸡最撒比的SOL提供. 寂月城网站是完美信息教室的官网.地址:http://191.101.11.174/mgzd . 题目描述 辣鸡蒟蒻SOL是一个傻逼,他居然觉得数 ...
- Android_Gallery(画廊)
转:http://blog.csdn.net/tianjf0514/article/details/7521398 Gallery是画廊的意思,可以实现图片的浏览功能. 主要内容 Gallery控件的 ...
- linux下常见的包安装方式
linux下常见的包安装方式 一.总结 一句话总结: rpm包安装 tar.gz源代码包安装 yum方式安装rpm包 bin文件安装 1.yum是什么? 安装所有依赖的软件包 Yum(全称为 Yell ...
- PandorBox 中安装aria2失败的解决办法
来自:http://www.right.com.cn/forum/thread-174358-1-1.html 不论luci界面还是opkg中安装,都提示缺少依赖包uclibc,pandorabox默 ...
- Java-Maven-pom.xml-project-repositories:repositories
ylbtech-Java-Maven-pom.xml-project-repositories:repositories <!--发现依赖和扩展的远程仓库列表. --> 1. platfo ...