20

For user authorization, I only want to include a specific module for each user. So I configured Conditional Compilation like this

<DefineConstants>TRACE;DEBUG;SAMPLECONSTANT1</DefineConstants>

and edited the project file like this:

<ProjectReference Include="..\Solution1.Modules.Module1\Solution1.Modules.Module1.csproj" Condition="$(DefineConstants.Contains('SAMPLECONSTANT1'))">
  <Project>{4E378BD0-4FF8-4160-9331-1ECBFD2B6F30}</Project>
  <Name>Solution1.Modules.Module1</Name>
</ProjectReference>

For this case I want to add reference to project Module1 if DefineConstants contains SAMPLECONSTANT1; but no matter what I put in DefineConstants, the solution always loads the Module1 project. What did I do wrong here?

UPDATE: Actually my code is correct. Please see J0e3gan's answer. Visual Studio UI does not reflect conditional references within the References folder of a project. Therefore all references are visible in any given configuration or platform selection. The compiler and IntelliSense on the other hand are aware of conditional references, honoring the correct settings both with visual feedback and error notification during builds.

J0e3gan
  • 8,740
  • 10
  • 53
  • 80
chinh nguyen van
  • 729
  • 2
  • 7
  • 18
  • 1
    Please could you elaborate more, it seems not clearly much – cuongle May 15 '13 at 04:24
  • Hi Cuong Le, I just update my question, for this question I want to add reference to project Module1 if DefineConstants contains SAMPLECONSTANT1, but whatever I put in DefineConstants, the solution always load Module1 project – chinh nguyen van May 15 '13 at 04:38
  • 1
    My thought is it would be better if you load module in runtime, not compile time. You can use reflection or MEF to do this. – cuongle May 15 '13 at 04:51
  • I worked on this a bit based on my understanding that you are truly trying to condition a project reference, not the inclusion of a project in a solution: I found an approach that worked well for me; and hopefully you will find that it works well for you. – J0e3gan May 15 '13 at 06:38

3 Answers3

30

I suspect the problem is that you are conditioning a project reference to Module1, not whether to include Module1 in the solution.

Including a project in a solution (and hence loading it with the solution) and a project referencing another project in a solution are two different things of course.

UPDATE:

If you truly want to condition a project reference, Joe Wrobel wrote a related blog post that should help. The key takeaway is to wrap the ItemGroup that contains the ProjectReference to condition in a Choose element - for example:

<Choose>
  <When Condition="$(DefineConstants.Contains('SAMPLECONSTANT1'))">
    <ItemGroup>
      <ProjectReference Include="..\Solution1.Modules.Module1\Solution1.Modules.Module1.csproj">
        <Project>{4E378BD0-4FF8-4160-9331-1ECBFD2B6F30}</Project>
        <Name>Solution1.Modules.Module1</Name>
      </ProjectReference>
      <!-- other ProjectReference elements -->
    </ItemGroup>
  </When>
  <Otherwise>
    <ItemGroup>
      <!-- other ProjectReference elements -->
    </ItemGroup>
  </Otherwise>
</Choose>

From my tests this evening, this works great to condition a project reference(s) on whether a constant like SAMPLECONSTANT1 is defined. However, note that conditioned project references do not show in Solution Explorer under the (would-be) referencing project's References folder - regardless whether the conditioning constant is defined.

To see that the conditioning worked, I had to build: with SAMPLECONSTANT1 defined, the referencing project built successfully while using a class defined in Module1 - as expected; and without SAMPLECONSTANT1 defined, the referencing project failed to build because the class defined in Module1 could not be resolved - also as expected.

J0e3gan
  • 8,740
  • 10
  • 53
  • 80
  • 2
    If I reference a DLL, not a project, it is working fine like this: ` ` Therefore I don't know why ProjectReference not work. – chinh nguyen van May 15 '13 at 05:41
  • 3
    Your answer is correct, I tested and it worked, I only checked in project's References folder and still see the Project, that is why I think my code did not work, so silly. For anyone who interested in this, you can use my code as well, it is simpler without using `Choose` or `When` tag :) – chinh nguyen van May 15 '13 at 06:42
  • @chinhnguyenvan: Right you are. How ironic: I had to work through the `Choose` approach to discover the References vs. build distinction - then find (prompted by your comment) that it makes the difference with your approach too! An MSDN [MSBuild thread](http://social.msdn.microsoft.com/Forums/en-US/msbuild/thread/893d475b-9e0c-485e-b89d-0e7b3712c84e/) somewhat discusses this. Now I wonder if Eugene Zakhareyev actually meant "You can surely tweak the references to make them conditional; the thing about it is that it will be[ ][in]visible in VS, and not editable through UI..." in his reply. – J0e3gan May 15 '13 at 07:17
  • 2
    @chinhnguyenvan: _Interesting_: so I nailed down the difference between your indications that the conditioned reference was always visible under References...and my experience that the conditioned reference(s) was always invisible. Using the `ProjectReference` element's `Condition` attribute, a conditioned project reference always shows under References - like you described; and using the `Choose`-`When` approach I outlined, a project reference(s) is always _in_visible under References. Bizarre. :) BTW, I tested everything with Visual Studio 2010 Professional SP1 for complete context. – J0e3gan May 15 '13 at 07:19
  • 1
    your indication is correct, both of our codes work, they are just [in]visible in References folder. Thank a lot for your help. – chinh nguyen van May 15 '13 at 07:55
1

The accepted answer did not work for me. However, I do not imply that it is incorrect. What worked for me is this:

<Import Project="..\MnM.GWS.Chip2\MnM.GWS.Chip1.projitems" Label="Shared" Condition="$(DefineConstants.Contains('Chip1'))" />
<Import Project="..\MnM.GWS.Chip2\MnM.GWS.Chip2.projitems" Label="Shared" Condition="$(DefineConstants.Contains('Chip2'))" />

I did not get any error while changing constants.

ChrisW
  • 54,973
  • 13
  • 116
  • 224
Mukesh Adhvaryu
  • 642
  • 5
  • 16
0

If you want to use the DEBUG constant make sure it is enabled in your project properties (Properteis > Build > Define DEBUG Constant).

Sample based on accepted answer:

  <Choose>
    <When Condition="$(DefineConstants.Contains('DEBUG'))">
      <ItemGroup>
        <ProjectReference Include="..\..\..\..\..\MyLocalProjectPath.csproj" />
      </ItemGroup>
    </When>
    <Otherwise>
      <ItemGroup>
        <PackageReference Include="MyNugetPackage" Version="2.1.4" />
      </ItemGroup>
    </Otherwise>
  </Choose>
Benni
  • 203
  • 2
  • 7