非web项目中使用XDT的实例

概述

XDT是Asp.net 4.0中的一个新特性,可以让使用者在Web项目中在不同的生成类型下,快速切换配置文件(如在debug场景下使用测试配置数据库,在Release场景下使用正式配置数据库)。 但在非web项目中,VS并未提供如此方便的功能。这时如果我们同样想使用xdt transforms的功能,就需要自己配置MSbuild文件。

在本例中我们是通过修改MSBuild配置文件,来使非web项目同样可以使用XDT功能。

MSBuild全称(Microsoft Build Engine),是用于构建应用程序的平台。可以把他简单的理解成Vs生成时的项目用配置,可以利用其中的配置信息对项目文件实施特定顺序的操作。

项目准备

新建一个控制台项目,并在项目中创建如下的文件:

其中app.config的内容

  <connectionStrings>
    <add name="DefaultConnection"
      connectionString="Data Source=TestSQLServer;Initial Catalog=MyTestDB;Integrated Security=True" providerName="System.Data.SqlClient"/>
  </connectionStrings>

app.debug.config的内容

<connectionStrings>
    <add name="DefaultConnection"
      connectionString="Data Source=Debug;Initial Catalog=MydebugDB;Integrated Security=True" providerName="System.Data.debug"
      xdt:Transform="Replace" xdt:Locator="Match(name)"/>
</connectionStrings>

app.release.config的内容

<connectionStrings>
    <add name="DefaultConnection"
      connectionString="Data Source=Debug;Initial Catalog=MydebugDB;Integrated Security=True" providerName="System.Data.debug"
      xdt:Transform="Replace" xdt:Locator="Match(name)"/>
</connectionStrings>

在控制台程序中输出你想看到的变化的配置文件

private static readonly string DifferentConfigString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
        static void Main(string[] args)
        {
            Console.Write(DifferentConfigString);
            Console.Read();
        }

整个的项目结构最后的呈现如下的样子(config会在具体配置后才变成如下的样子):

具体实现:

1. 项目中引用Msbuild

2. 在系统创建%ProgramFiles (x86)%\MSBuild\Custom文件夹,把本文末尾的TransformFiles.targets文件拷贝到文件夹中,注意要修改文件中的版本号跟你安装的Msbuild版本号一致。(本文中为简化例子,只介绍这一种配置方式,团队协作的配置或者单独项目的配置会在后续的文章中说明)

3. 右键点击项目->卸载项目->右键点击项目->编辑.csproj 项目文件

4. 在项目文件结尾的</Project> tag上,插入如下代码

<Import Project="$(MSBuildExtensionsPath)\Custom\TransformFiles.targets" />

5. 在项目文件中,给那些你想转换的文件一个metadata,把TransformOnBuild设置成true.

在本例中,修改项目文件中的<None Include="App.config" />为

 <None Include="App.config">
          <TransformOnBuild>true</TransformOnBuild>
</None>

修改<None Include="App.Debug.config" /><None Include="App.Release.config" />为

 <None Include="App.Debug.config">
          <DependentUpon>app.config</DependentUpon>
        </None>
        <None Include="App.Release.config">
          <DependentUpon>app.config</DependentUpon>
</None>

6. 重新加载项目

7. 切换解决方案配置,运行程序发现配置文件已经会自动使用不同的app.config中的内容

示例效果

在debug环境下自动使用debug参数

在release版本里自动使用release参数

实现原理

TransformFile.targets 含有两个目标(target):DiscoverFilesToTransform,TransformAllFiles。

其中。DiscoverFilesToTransform会浏览所有的项 (None, Content, and Resource)。 在DiscoverFilesToTransform我查找含有%(TransformOnBuild)==true的值。当收集到所有的值以后,识别出是否有一个“app.config”会被转换,如果是,把它放在一个特殊的项列表中,并且把其他的放在另一个项列表中。

在TransformAllFiles 中,TransformXml 任务被用来转换所有的文件。使用属性AfterTargets="Build;_CopyAppConfigFile",目标得以把自己注入到生成进程中。 每当生成或者_CopyAppConfigFile目标被调用,TransformAllFiles目标会被执行

以下是TransformFiles.targets文件的所有代码

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask TaskName="TransformXml"
         AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.Tasks.dll"/>

  <ItemDefinitionGroup>
    <!-- Set the default value to false here -->
    <None>
      <TransformOnBuild>false</TransformOnBuild>
    </None>
    <Content>
      <TransformOnBuild>false</TransformOnBuild>
    </Content>
    <Resource>
      <TransformOnBuild>false</TransformOnBuild>
    </Resource>
    <EmbeddedResource>
      <TransformOnBuild>false</TransformOnBuild>
    </EmbeddedResource>

    <_FilesToTransform>
      <IsAppConfig>false</IsAppConfig>
    </_FilesToTransform>
  </ItemDefinitionGroup>

  <PropertyGroup>
    <TransformAllFilesDependsOn>
      DiscoverFilesToTransform;
    </TransformAllFilesDependsOn>
  </PropertyGroup>
  <Target Name="TransformAllFiles" DependsOnTargets="$(TransformAllFilesDependsOn)" AfterTargets="Build;_CopyAppConfigFile">
    <!-- Now we have the item list _FilesToTransformNotAppConfig and _AppConfigToTransform item lists -->
    <!-- Transform the app.config file -->
    <ItemGroup>
      <_AppConfigTarget Include="@(AppConfigWithTargetPath->‘$(OutDir)%(TargetPath)‘)" />
    </ItemGroup>

    <PropertyGroup>
      <_AppConfigDest>@(_AppConfigTarget->‘%(FullPath)‘)</_AppConfigDest>
    </PropertyGroup>

    <MakeDir Directories="@(_FilesToTransformNotAppConfig->‘$(OutDir)%(RelativeDir)‘)"
             Condition="Exists(‘%(RelativeDir)%(Filename).$(Configuration)%(Extension)‘)"/>

    <TransformXml Source="@(_AppConfigToTransform->‘%(FullPath)‘)"
                  Transform="%(RelativeDir)%(Filename).$(Configuration)%(Extension)"
                  Destination="$(_AppConfigDest)"
                  Condition=" Exists(‘%(RelativeDir)%(Filename).$(Configuration)%(Extension)‘) " />

    <TransformXml Source="@(_FilesToTransformNotAppConfig->‘%(FullPath)‘)"
                  Transform="%(RelativeDir)%(Filename).$(Configuration)%(Extension)"
                  Destination="@(_FilesToTransformNotAppConfig->‘$(OutDir)%(RelativeDir)%(Filename)%(Extension)‘)"
                  Condition=" Exists(‘%(RelativeDir)%(Filename).$(Configuration)%(Extension)‘) " />
  </Target>

  <Target Name="DiscoverFilesToTransform">
    <!--
    This will look through items list: None & Content for those
    with Metadata <TransformOnBuild>True</TransformOnBuild>
    -->
    <ItemGroup>
      <_FilesToTransform Include="@(None);@(Content);@(Resource);@(EmbeddedResource)"
                         Condition=" ‘%(TransformOnBuild)‘ == ‘true‘ "/>
    </ItemGroup>    

    <PropertyGroup>
      <_AppConfigFullPath>@(AppConfigWithTargetPath->‘%(RootDir)%(Directory)%(Filename)%(Extension)‘)</_AppConfigFullPath>
    </PropertyGroup>

    <!-- Now look to see if any of these are the app.config file -->
    <ItemGroup>
      <_FilesToTransform Condition=" ‘%(FullPath)‘==‘$(_AppConfigFullPath)‘ ">
        <IsAppConfig>true</IsAppConfig>
      </_FilesToTransform>
    </ItemGroup>

    <ItemGroup>
      <_FilesToTransformNotAppConfig Include="@(_FilesToTransform)"
                                     Condition=" ‘%(IsAppConfig)‘!=‘true‘"/>

      <_AppConfigToTransform  Include="@(_FilesToTransform)"
                              Condition=" ‘%(IsAppConfig)‘==‘true‘"/>
    </ItemGroup>
  </Target>
</Project>

也可以在这里下载

其他

了解XDT:http://www.cnblogs.com/JustRun1983/p/3418844.html

了解MSbuild:http://www.cnblogs.com/l_nh/archive/2012/08/30/2662648.html

本文来源于:http://sedodream.com/2010/11/18/XDTWebconfigTransformsInNonwebProjects.aspx

时间: 2024-08-24 18:29:33

非web项目中使用XDT的实例的相关文章

非web项目中使用XDT的实例(续)

简化 上个实例中,我们是引用了target文件来遍历项目中的xdt项. 当项目比较小,我们又只需要针对固定的config文件进行更替时,可以使用更简化的方法 不进行项目配置文件中的插入<Import Project="$(MSBuildExtensionsPath)\Custom\TransformFiles.targets" /> 而直接写入代码 <UsingTask TaskName="TransformXml" AssemblyFile=&q

Jfinal数据库操作在WebService或非web项目中的使用

接触上jfinal后就基本不使用其它框架了,一直在web开发中使用,最近做了个小的WebService应用,还是使用jfinal操作数据库,在这里分享下使用经验. 我的环境是三个oracle数据库,一个数据库接收数据,然后分发数据到另外两个数据库,使用jfinal的多数据源功能刚好满足要求. 编写数据库初始化类: 直接上代码 package ynitil.pekk.ws.common; import java.util.List; import ynitil.pekk.ws.model.Cltx

非WEB项目中引入Hibernate Validator

前言: 网上一些朋友分享了关于hibernate-validator的使用方法,但是不是缺少关联库信息,就是提供的参考代码中缺少自定类. 希望我这一篇博客能够让你顺利的跑出预期的结果. 如果有错,可以给我留言. 英文好的朋友可以参考官网的getting started. http://hibernate.org/validator/documentation/getting-started/ 一.环境 hibernate-validator库必须运行的JDK版本为1.6及以上. 二.hibern

【.net深呼吸】非 Web 项目使用缓存

从.net 4 开始,非web项目也可以使用缓存技术,故曰:.net 4 乃框架成熟之标志也. 对于缓存嘛,耍过 ASP.NET 的伙伴们肯定知道,这么说吧,就是将一些使用频率较高的数据放于内存中,并设置一个过期时间(比如30秒),只要缓存数据还没有过期,下一次在访问数据时就可以直接从缓存加载,而不需要重新读取.你想啊,如果数据是从数据库中读取的,或者通过网络从其他地方获得的,那么,采用缓存技术,就可以减少读取数据的次数,绿色环保. 当然了,要实时更新的内容就不能放到缓存中了,比如实时在线视频,

Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问

本篇内容还是建立在上一篇Java Web学习系列——Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Jar包 这部分内容需要以下Jar包支持 mysql-connector:MySQL数据库连接驱动,架起服务端与数据库沟通的桥梁: MyBatis:一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架: log4j:Apache的开源项目,一个功能强大的日志组件,提供方便的日志记录: 修改后的pom.xm

编写高质量代码改善java程序的151个建议——[110-117]异常及Web项目中异常处理

原创地址:http://www.cnblogs.com/Alandre/(泥沙砖瓦浆木匠),需要转载的,保留下! 文章宗旨:Talk is cheap show me the code. 大成若缺,其用不弊.大盈若冲,其用不穷.  <道德经-老子>最完满的东西,好似有残缺一样,但它的作用永远不会衰竭:最充盈的东西,好似是空虚一样,但是它的作用是不会穷尽的 Written In The Font 摘要: 异常处理概述 学习内容: 建议110: 提倡异常封装 建议111: 采用异常链传递异常 建议

在Java Web项目中引入Mondrian多维分析框架

一,Mondrian简介 Mondrian是一个开源项目,一个用Java写成的OLAP引擎.它用MDX语言实现查询,从关系数据库(RDBMS)中读取数据.然后经过Java API以多维的方式对结果进行展示. Mondrian的使用方式同JDBC驱动类似.可以非常方便的与现有的Web项目集成. Mondrian OLAP 系统由四个层组成,可分为从最终用户到数据中心, 顺序为: 1表现层(the presentation layer) 2维度层(the dimensional layer) 3集合

在Web项目中使用MEAN堆栈的7大理由

Web开发的过程中会涉及各种技术的应用,其中比较突出的是Web服务器.库.前端框架和数据库系统.如今,开发人员使用工具和技术的结合来更加方便和快捷地进行web开发.例如,LAMP,Linux(操作系统).Apache(Web服务器).MySQL(数据库管理系统)和PHP.Perl或Python(服务器端脚本语言).同样,在Web开发中一个新的技术堆栈也越来越受到开发人员的欢迎,而MEAN就是这样一个堆栈! MEAN是MongoDB.Express.AngularJS 和 Node.js的首字母缩

web项目中的 log4net的配置

最近用log4net,网上查了很多资料,照着网上的配置大多都不管用,可能我还是有什么地方配置的不对.看出来的朋友平指出.下面是我自己亲测的,可以用! 1.web项目中的web.config 配置log4net <?xml version="1.0" encoding="utf-8"?> <!-- 有关如何配置 ASP.NET 应用程序的详细消息,请访问 http://go.microsoft.com/fwlink/?LinkId=169433 --