你的位置:首页 > ASP.net教程

[ASP.net教程]非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 中,Transform

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

<?"1.0" encoding="utf-8"?><Project "http://schemas.microsoft.com/developer/msbuild/2003"> <UsingTask TaskName="Transform"     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)')"/>    <Transform"@(_AppConfigToTransform->'%(FullPath)')"         Transform="%(RelativeDir)%(Filename).$(Configuration)%(Extension)"         Destination="$(_AppConfigDest)"         Condition=" Exists('%(RelativeDir)%(Filename).$(Configuration)%(Extension)') " />    <Transform"@(_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