title author date CreateTime categories
Roslyn 如何在 Target 引用 xaml 防止文件没有编译
lindexi
2019-07-09 17:16:26 +0800
2018-09-04 08:54:27 +0800
Roslyn MSBuild 编译器 xaml 打包

在使用新的项目格式,可以使用 Target 添加项目,但是有一些项目需要在合适的时候添加,如果添加早了,那么会让用户看到这些文件,如果添加的时间是在引用编译之后,那么文件将无法进行编译。

本文是更多请看手把手教你写 Roslyn 修改编译 的一个文章,在开始本文之前,假设大家已经了解 Roslyn 相关。

本文主要是我自己探索 VisualStudio 编译的过程,所以有一点乱,主要的过程就是遇到了将 xaml 写在了 Traget 里,编译的时候因为找不到 xaml 编译,所以无法编译通过。

于是我就不断在早一个 Target 在这个 Target 之前添加编译 xaml 就可以让 VisualStudio 编译通过

先来说结论

通过 BeforeTargets="GenerateBindingRedirects" 里添加 xaml 文件就可以让 VisualStudio 编译的时候编译添加 xaml 编译。

但一个准确的时机是 BeforeTargets="MarkupCompilePass1" 里面添加 xaml 文件,详细请看 WPF 程序的编译过程

本文以下的内容只是记录我做过的测试

也就是通过下面代码添加的 MainPage.xaml 可以被编译

  1. <Target Name="MoqakermirLaqouLurter" BeforeTargets="GenerateBindingRedirects">
  2. <ItemGroup>
  3. <Page Include="MainWindow.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>
  4. </ItemGroup>
  5. </Target>

下面是记录过程,如果只是想要知道结论,那么下面的文章就不需要看了。

首先来创建一个空白的 WPF 程序,使用从以前的项目格式迁移到 VS2017 新项目格式的方法修改 WPF 程序为新项目格式,然后开始来修改 xaml 的加入时间。

一个空白的 WPF 程序会包含这些内容

compile 编译的文件

  1. App.xaml.cs
  2. MainWindow.xaml.cs
  3. Program.cs
  4. Properties\AssemblyInfo.cs
  5. Properties\Resources.Designer.cs
  6. Properties\Settings.Designer.cs
  7. C:\Users\lindexi\AppData\Local\Temp\.NETFramework,Version=v4.5.AssemblyAttributes.cs
  8. obj\Debug\net45\TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs
  9. obj\Debug\net45\TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs
  10. obj\Debug\net45\TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs
  11. D:\lindexi\github\BemateRaimarhas\obj\Debug\net45\App.g.cs
  12. D:\lindexi\github\BemateRaimarhas\obj\Debug\net45\MainWindow.g.cs
  13. D:\lindexi\github\BemateRaimarhas\obj\Debug\net45\BemateRaimarhas_Content.g.cs
  14. obj\Debug\net45\BemateRaimarhas.AssemblyInfo.cs

EmbeddedResource 嵌入资源

  1. Properties\Resources.resx

None 无编译文件

  1. App.config
  2. App.xaml
  3. MainWindow.xaml
  4. Properties\Settings.settings

Page 页面文件

  1. App.xaml
  2. MainWindow.xaml

默认没有包含内容和资源文件

注意,默认空白的项目在页面文件和无编译文件存在 MainWindow.xaml 等文件。这些文件是重复的,可以使用下面代码去掉无编译的 MainWindow.xaml 文件

  1. <None Remove="**\*.xaml"></None>

如果尝试去掉下面的代码,也就是所有的 xaml 文件都没有添加编译

  1. <Page Include="**\*.xaml">
  2. <SubType>Designer</SubType>
  3. <Generator>MSBuild:Compile</Generator>
  4. </Page>

这时会出现编译不通过

  1. MainWindow.xaml.cs(25,13): Error CS0103: 当前上下文中不存在名称“InitializeComponent
  2. Program.cs(15,17): Error CS1061: App”未包含“InitializeComponent”的定义,并且找不到可接受第一个“App”类型参数的可访问扩展方法“InitializeComponent”(是否缺少 using 指令或程序集引用?)

那么现在尝试使用 Target 来添加这两个文件,为什么需要使用 Target 而不是直接写 ItemGroup 是因为我需要在用户的 VisualStudio 看不到这些文件。很多时候可以使用 Visible="False" 隐藏文件,但是如果这个文件刚好放在一个文件夹里面,那么这个文件夹将会被用户看到。也就是用户可以删除这个文件夹,一旦这个文件夹删了,那么文件夹里面的文件也就是无法编译通过,这时小伙伴就会过来打我

  1. <Page Include="App.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>
  2. <Page Include="MainWindow.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>

一开始我就知道将文件放在 Target 里可以设置让用户看不到引用的文件,写一个 Target 需要包含一个 Name 所以我就写出下面代码

  1. <Target Name="MoqakermirLaqouLurter">
  2. <ItemGroup>
  3. <Page Include="App.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>
  4. <Page Include="MainWindow.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>
  5. </ItemGroup>
  6. </Target>

当然,上面的 Page 是不会被添加的,原因是 MSBuild 不知道什么时候运行上面的代码。为了让 MSBuild 运行上面的 Target 我就需要给 BeforeTargets 在一开始我就尝试用的比较多的 CoreCompile 请看代码

  1. <Target Name="MoqakermirLaqouLurter" BeforeTargets="CoreCompile">
  2. <ItemGroup>
  3. <Page Include="App.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>
  4. <Page Include="MainWindow.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>
  5. </ItemGroup>
  6. </Target>

上面的代码会在 BeforeTargets="CoreCompile" 运行,但是还是无法编译通过

于是就找到了 XamlPreCompile 替换 CoreCompile 请看下面

  1. <Target Name="MoqakermirLaqouLurter" BeforeTargets="XamlPreCompile">
  2. <ItemGroup>
  3. <Page Include="App.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>
  4. <Page Include="MainWindow.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>
  5. </ItemGroup>
  6. </Target>

但是在 MSBuild 是没有运行 XamlPreCompile 的,所以上面的代码没有运行,也是编译不通过

尝试使用 GenerateBindingRedirects 替换 XamlPreCompile 请看下面

  1. <Target Name="MoqakermirLaqouLurter" BeforeTargets="GenerateBindingRedirects">
  2. <ItemGroup>
  3. <Page Include="App.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>
  4. <Page Include="MainWindow.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>
  5. </ItemGroup>
  6. </Target>

现在就可以编译通过了,而且在用户的代码也看不到 xaml 文件,我就是通过这个方法开发。也就是经过了 CoreCompil XamlPreCompile 找到了 GenerateBindingRedirects 可以解决文件引用。

那么相比写在 ItemGroup 而不经过 Target 有什么好处?

如果这时将会 MainWindow.xaml 放在了一个文件夹 View 只要有引用这个文件,无论有没设置是否隐藏,开发者都可以看到 View 文件夹,而且可以删除这个文件夹,如果删除了这个文件夹,那么就无法编译

如使用下面的代码,即使设置 MainWindow.xaml 不可见,但是用户还是可以在 VisualStudio 看到一个空文件夹

  1. <ItemGroup>
  2. <Page Include="App.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>
  3. <Page Include="View\MainWindow.xaml" SubType="Designer" Generator="MSBuild:Compile" Visible="False"></Page>
  4. </ItemGroup>

但是如果放在 Target 里就无法看到引用的文件夹,也就无法删除文件夹,通过这个方法可以让我使用源代码打包

如使用下面的代码,即使没有设置 MainWindow 不可见,用户也是看不见这个文件

  1. <Target Name="MoqakermirLaqouLurter" BeforeTargets="GenerateBindingRedirects">
  2. <ItemGroup>
  3. <Page Include="App.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>
  4. <Page Include="View\MainWindow.xaml" SubType="Designer" Generator="MSBuild:Compile"></Page>
  5. </ItemGroup>
  6. </Target>

源代码打包项目是为了解决很小的代码,都需要做出一个 nuget 包,这个 nuget 包是 dll 也就是软件会引用太多的 dll ,大家都知道如果引用的 dll 多了,软件启动速度也就是变慢了。所以我就使用打包 nuget 包但是引用的是源代码的方式,这样开发者在安装 nuget 之后可以快速调试安装的库的源代码。

项目请看: 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.

参见:手把手教你写 Roslyn 修改编译

2019-7-9-Roslyn-如何在-Target-引用-xaml-防止文件没有编译的更多相关文章

  1. 直接引用MrAdvice.dll文件不能实现AOP拦截,教你1分钟解决这个问题

    直接引用MrAdvice.dll文件不能实现AOP拦截,教你1分钟解决这个问题.近日工作中,要实现一个功能,那就是业务层方法里面实现自动缓存.编写业务的C#开发人员只关注如何将业务代码编写正确就可以了 ...

  2. 编写 Target 检测 MSBuild / dotnet build 此次编译是否是差量编译

    MSBuild 或 Roslyn 编译项目时均支持差量编译,毕竟为了性能.我在 每次都要重新编译?太慢!让跨平台的 MSBuild/dotnet build 的 Target 支持差量编译 一文中介绍 ...

  3. chrome调试本地项目, 引用本地javascript文件

    chrome调试本地项目, 引用本地javascript文件 本地文件可以访问本地文件 修改快捷方式属性 C:\Users\xxx\AppData\Local\Google\Chrome\Applic ...

  4. JS引用另外JS文件的顺序问题。

    1.在a.js中可以引用b.js文件,这样就可以在网页中只引用a.js文件,从而可以使用a.js和b.js文件中的所有方法. 引用格式如下:document.write('<script typ ...

  5. Windows Store App 全球化:引用分离资源文件中的资源

    大部分应用程序仅需要单个默认资源文件,例如Strings/zh-CN/Resources.resw,但是在某些应用程序中,最好将资源分离到多个资源文件中,以便更好地组织资源内容,这样就需要考虑如何引用 ...

  6. C# 动态修改dll的签名 以及修改引用该dll文件的签名

    在读取RedisSessionStateProvider配置 提到用mono ceil 来修改程序集以及它的签名,里面GetPublicKey 和GetPubliKeyToken 方法里面那个字符串的 ...

  7. Makefile第四讲:include 引用其它makefile文件

    main.cpp #include "classes/fun.h" int main() { Test::display("Hello makefile"); ...

  8. node.js如何引用其它js文件

    以Java来说,比如要实现第三方存储,我可能需要导入对应的库,以maven为例,使用腾讯云或者七牛云.阿里云,我需要导入对应的maven依赖.再比如,有些时候我们封装某个类,而那个类不在该包下,我们需 ...

  9. 2019/01/17 基于windows使用fabric将gitlab的文件远程同步到服务器(git)

    觉得django项目把本地更新push到gitlab,再执行fabric脚本从gitlab更新服务器项目挺方便的,当然从本地直接到服务器就比较灵活. 2019/01/17 基于windows使用fab ...

  10. Java中带包(创建及引用)的类的编译

    Java中带包(创建及引用)的类的编译与调试 java源程序的编译大家都知道,也就是cmd中到源文件所在目录下javac **.java即可,当程序中有包声明还能简简单单的直接javac **.jav ...

随机推荐

  1. 面试系列15 如何保证Redis的高并发和高可用

    就是如果你用redis缓存技术的话,肯定要考虑如何用redis来加多台机器,保证redis是高并发的,还有就是如何让Redis保证自己不是挂掉以后就直接死掉了,redis高可用 我这里会选用我之前讲解 ...

  2. css盒模型问题

    css盒模型问题 1.基本概念:标准模型和ie模型 2.标准模型和ie模型的区别 3.css如果设置这两种模型 4.js如何获取盒模型的宽高 5.边距重叠 6.BFC 1.CSS盒模型本质上是一个盒子 ...

  3. springcloud Eureka Finchley.RELEASE 版本

    创建一个父项目cloud-demo pom.xml <?xml version="1.0" encoding="UTF-8"?> <proje ...

  4. apache反向代理和监听多个端口设置

    修改apache配置文件httpd.conf 一.监听多个端口 在Listen 80后添加监听端口,如 Listen 80 Listen 8080 Listen 8008 二.反向代理设置 1.取消一 ...

  5. LuoguP3498 [POI2010]KOR-Beads

    呀呀呀,临走10分钟刷一道水题 然而只是记一下第一次hash被卡 各种模数都被卡了... 本来想打双哈希了,后来皮了一下,模数改成了998244353,然后竟然A掉了 正着hash一遍,反着hash一 ...

  6. [Noip 2013 Day1-3] 货车运输 做法总结

    [Noip 2013 Day1-3] 货车运输 做法总结 Online Judge:Luogu-1967 Label:启发式合并,离线,整体二分,按秩合并,倍增,最大生成树 打模拟离线赛时做到,顺便总 ...

  7. thinkphp Mongo模型

    Mongo模型是专门为Mongo数据库驱动而支持的Model扩展,如果需要操作Mongo数据库的话,自定义的模型类必须继承Think\Model\MongoModel. Mongo模型为操作Mongo ...

  8. HttpUrlConnection post 乱码 终极解决方案

    今天遇到了java后台模拟http请求,以POST方式传参中文乱码,google了一下,大部分是在打开的HttpURLConnection的输入流的时候设置编码(utf-8),按照设置,试了下并没有解 ...

  9. vue2 + koa2全栈部署

    1.首先打包前端上传 修改config下的index.js 代理地址为服务器IP index: path.resolve(__dirname, '../dist/index.html'), asset ...

  10. Maven的作用及简介

    Maven的作用及简介 一.maven作用 项目之间都是有依赖的,比如A项目依赖于B项目,B项目依赖与C.D项目,等等.这样的依赖链可能很长. 但是,没有一个项目的jar包我们都要导入进去,我们要做的 ...