How to use different files in a project for differ

2020-02-23 11:01发布

问题:

I have a c# .net winforms solution and I want to create two different builds: one that supports IE6 and one that supports IE7. A few of the files in one of my projects are different for the IE6 build versus the IE7 build, so I want to include the IE6 files when I build for IE6 and the IE7 files when I build for IE7. What's the best way of structuring my solution for this situation?

Due to other constraints I do not want to create a separate assembly that contains the shared items; I want the project to compile to a single assembly 'foo.dll' regardless of which build I'm making.

I thought I could just create two separate projects that compile to 'foo.dll', then create two Release Configurations and only include the relevant project in the relevant configuration. However I'd need to include the files that are the same for IE6 and IE7 in both projects, and I can't see how to use a single copy of a file in two projects (when I Add Existing Item it creates a copy in the project directory). I'm using SVN for source control so could perhaps use that to do the 'sharing' between folders, but doubt that's the best way..

NB: Different builds are needed due to API differences in IE, details of which aren't relevant to the question - just believe me that there are two builds required.

回答1:

In MSBuild, you can specify conditions to item groups. You can then bind those conditions to the target device.

Example:

<!-- Declare the condition property at the beggining of the build file -->
<PropertyGroup Condition="$(Platform) == 'IE7'">
  <UseNewLibrary>true</UseNewLibrary>
</PropertyGroup>

<PropertyGroup Condition="$(Platform) == 'IE6'">
  <UseNewLibrary>false</UseNewLibrary>
</PropertyGroup>


<!-- Then those the property to select the right file -->
<ItemGroup Condition="$(UseNewLibrary)==true">
  <Compile Include="Class1.cs"/>
  <Compile Include="Class2.cs"/>
  <Compile Include="Class3.cs"/>
  <Compile Include="Class4.cs"/>
</ItemGroup>

<ItemGroup Condition="$(UseNewLibrary)==false">
   <Compile Include="Class1Old.cs"/>
   <Compile Include="Class2Old.cs"/>
   <Compile Include="Class3Old.cs"/>
   <Compile Include="Class4Old.cs"/>
</ItemGroup>

<!-- And now references -->
<ItemGroup Condition="$(UseNewLibrary)==true">
  <Reference Include="MyAssembly, Version=1.1.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</ItemGroup>

<ItemGroup Condition="$(UseNewLibrary)==false">
  <Reference Include="MyAssembly, Version=1.0.6.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</ItemGroup>

Note that all files will appear in the IDE, but at compile time everything should align correctly.

Then, all you need to do is create your platforms (IE6 and IE7) in the configuration management.

You can also directly use the platform property instead of creating an intermediate property.



回答2:

In order to add the same file in two or more projects you can

Right click on the project and choose Add >> Existing Item
Choose the file in the filepicker
Click the little triangle on the right side of the Add button in the file picker
Choose Add As Link

This will add the file to the project without making a copy of it.

I don't know all the details of your situation, but you're solution sounds awkward. Two versions of the same dll is likely to lead to configuration problems on client computers eventurally. I encourage you to consider Kevin's idea of a single dll with all capabilities, and calling the appropriate code as needed.



回答3:

Assuming you are using VS2005 or above you can use the Condition property in the project file.

You'll need to edit the csproj file directly

  1. Unload project
  2. Edit

then on the files you want to conditionally include

<Compile Include="IE6.cs" Condition=" '$(Platform)' == 'IE6' " />
<Compile Include="IE7.cs" Condition=" '$(Platform)' == 'IE7' " />
<Compile Include="IE.cs"  />


回答4:

I'm not sure how to do what you're asking, but couldn't you just include both versions of your API wrapper in the dll and determine which one to call at runtime? For example, what if a user installs the IE6 version of your app then upgrades to IE7? They'll need to reinstall, right?

It seems to me like this would be a much simpler solution, but maybe I'm missing something...