Conditional project or library reference in Visual Studio


Conditional project or library reference in VisualStudio

In case you were wondering why you haven’t heard from me in a while, I’ve been busy, which isn’t really of much importance unless you know me on a personal level. What is relevant is that I recently graduated witha master in Game and Media Technologyand am now in the process of making the project which I have been working on for my thesis open source. I’m very anxious to announce it, so you’ll read a lot more about it in the near future.

The project uses two of my other open source libraries, located in separate repositories. Adding these projects to the solution andreferencing them as project referenceshas the advantage of easier debugging and facilitates making changes to them. However, I do not want to force anyone interested in making changes to the main project to having to download the other repositories as well. Therefore I opted to useDLL references.This has one major downside. Whenever I do make changes to one of the dependent libraries, I need to manually copy the newly compiled DLLs to the main project.Wouldn’t it be easy to usetwo separate solution files, one with project references, and one with DLL references?

The first problem you’ll encounter is project references aren’t stored in the.slnfile but in the.csprojfile, which makes sense really. Since the.csprojfile is shared by both solutions, we’ll have toconditionally reference either our DLLs or our projects, depending on which solution the project is opened in.This is possible usingMSBuild, but you will need tocreate a new project configuration. Setting the configuration of the project differently in one solution from the other allows you to differentiate between the two of them. The following is part of a.csprojfile which conditionally loads a reference by checking whether the project configuration is set to ‘Debug With Project References’.

<Choose>
  <When Condition="'$(Configuration)' == 'Debug With Project References'">
    <ItemGroup>
      <ProjectReference Include="..\SomeProject\SomeProject.csproj">
        <Project>{6CA7AB2C-2D8D-422A-9FD4-2992BE62720A}</Project>
        <Name>SomeProject</Name>
      </ProjectReference>
    </ItemGroup>
  </When>
  <Otherwise>
    <ItemGroup>
      <Reference Include="SomeProject">
        <HintPath>..\Libraries\SomeProject.dll</HintPath>
      </Reference>
    </ItemGroup>
  </Otherwise>
</Choose>

You could very well stop here, but I wanted to resolve another issue as well. Unless you follow a really strict folder structure, and force everyone else who wants to open your solution to do the same,the path used to reference the project can varybetween people. Remember we are usingseparate repositorieshere, and the referenced projects aren’t included in the repository of the main solution, so relative paths don’t necessarily work. It is possible to specify the paths inan external ‘configuration’ file, and importing it into the.csprojfile. Additionally, as afallback when the project can’t be foundat the given path, it is also useful to load the DLL instead. This way you can choose to load one or more, but not necessarily all references as a project reference.

The configuration file (ProjectReferences.txt):

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="$(Configuration) == 'Debug With Project References'">
    <SomeProject>..\SomeProject</SomeProject>
  </PropertyGroup>
</Project>

Segment from the.csprojfile:

<Import Project="..\ProjectReferences.txt" />
<Choose>
  <When Condition="Exists($(SomeProject))">
    <ItemGroup>
      <ProjectReference Include="$(SomeProject)\SomeProject.csproj">
        <Project>{6CA7AB2C-2D8D-422A-9FD4-2992BE62720A}</Project>
        <Name>SomeProject</Name>
      </ProjectReference>
    </ItemGroup>
  </When>
  <Otherwise>
    <ItemGroup>
      <Reference Include="SomeProject">
        <HintPath>..\Libraries\SomeProject.dll</HintPath>
      </Reference>
    </ItemGroup>
  </Otherwise>
</Choose>

Notice the project configuration check now occurs in the configuration file. The ‘$(SomeProject)’propertyis only set when using the ‘Debug With Project References’configuration, thus in all other scenarios the DLL will be loaded instead since the ‘Exists()‘ check will fail.

One last issue remains. We still need tomanually copy the latest compiled DLLsto the ‘Libraries’folder when changes were made for the solution which uses them to work as expected. We can exploit the fact that we now have the relevant project paths available in the configuration file. Using a post build event you can call a script which parses the XML data, and copies the DLLs to the correct location. This script should be called conditionally, only for the solution which includes the project references, and ideally also only for aReleasebuild. I useda small Ruby scriptwhich offers a lot more flexibility than a Batch script.

The post build event:

if "$(SolutionName)" == "SomeSolution With Project References" if "$(ConfigurationName)" == "Release" ruby $(SolutionDir)UpdateLibraryDlls.rb $(SolutionDir)

优质内容筛选与推荐>>
1、C#.Net Core 操作Docker中的redis数据库
2、Memcached(二)Memcached Java API基础之MemcachedClient
3、使用MultFile.js实现多文件上传
4、UVALive 6697 Homework Evaluation
5、显示dll里的QWidget


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn