Code reuse across .NET and Monotouch has been addressed in many ways, but most techniques involve parallel sets of projects/solutions.
I'd like this question to clarify whether it is possible to build, using a single csproj file, either a .NET or a MonoTouch version of the same assembly, based on the selected Platform and Configuration.
Assume the following:
Question: Given these assumptions, can the library be
based on the current Visual Studio Platform and Configuration?
Current Research
<NoStdLib>true</NoStdLib>
in the .csproj while building for MonoTouch, together with different HintPath
s for System, System.Core, System.Xml etc seem necessary.Turns out this is in fact quite possible with MSBuild. The key points, assuming you're starting out with a C# project created for Windows .NET that you want to also compile for iOS are as follows. Note: this does not work with MonoDevelop. It only works with Visual Studio. This is because MonoDevelop does not currently use a full-fledged MSBuild compatible build system for MonoTouch.
For the iOS platform, set NoStdLib to true to avoid automatically referencing mscorlib.dll. Also set the path to a directory that contains local copies of the MonoTouch dll's, copied from your MonoTouch installation on a Mac:
<PropertyGroup Condition="'$(Platform'=='iOS'">
<NoStdLib>true</NoStdLib>
<iOSLibs>c:\MonoTouch\</iOSLibs>
</PropertyGroup>`
Add references to local copies of all referenced MonoTouch assemblies from the folder:
<ItemGroup Condition="'$(Platform'=='iOS'">
<Reference Include="mscorlib">
<HintPath>$(iOSLibs)\mscorlib.dll</HintPath>
</Reference>
<Reference Include="System">
<HintPath>$(iOSLibs)\System.dll</HintPath>
</Reference>
<Reference Include="System.Core">
<HintPath>$(iOSLibs)\System.Core.dll</HintPath>
</Reference>
<Reference Include="System.Xml">
<HintPath>$(iOSLibs)\System.Xml.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq">
<HintPath>$(iOSLibs)\System.Xml.Linq.dll</HintPath>
</Reference>
<Reference Include="monotouch">
<HintPath>$(iOSLibs)\monotouch.dll</HintPath>
</Reference>
</ItemGroup>
Visual Studio automatically adds an ItemGroup referencing all the .NET assemblies. Since we've instructed Visual Studio/MSBuild to get these from the iOSLibs folder when building for iOS, we should conditionally disable the default assemblies. This stops VS from complaining about duplicate assembly references. Change the first line of the ItemGroup
and add the condition as follows. (Note: the list of assemblies will differ depending on what your project currently references.)
<ItemGroup Condition=" '$(Platform)' != 'iOS' ">
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
Now you're ready to go. Once you have done this for all the projects in your solution, you can select iOS from the Solution drop down and build MonoTouch binary-compatible assemblies like magic, without the use of Portable Class Libraries! (This does not mean that PCLs are not useful, they certainly are, but the technique shown here is much more generally applicable.)
A more detailed knowledge of MSBuild and its considerable power will help you simplify even more, e.g.:
<DefineConstants>...</DefineConstants>
to allow your code to do things differently based on the current solution and configuration.