3

跨 .NET 和 Monotouch 的代码重用已通过多种方式解决,但大多数技术都涉及并行的项目/解决方案集。

我想通过这个问题来澄清是否可以根据所选的平台和配置,使用单个 csproj 文件构建同一程序集的 .NET 或 MonoTouch 版本。

假设如下:

  1. 构建机器运行 Windows。
  2. Visual Studio 和 MSBuild 可用。
  3. 该方法不需要在 MonoDevelop 上工作,因为 MonoDevelop 目前没有为 MonoTouch 打开 XBuild/MSBuild。
  4. 来自有效 MonoTouch 安装的 MonoTouch 二进制文件可用。
  5. 只需要构建一个库,而不是一个完整的应用程序。这个库:
    1. 不包含任何 .xib 或 plist。
    2. 是否使用平台特定的代码,这些代码将被有条件地编译。
    3. 是否(必须)引用特定于平台的程序集,这些需要由 .csproj 文件处理。

问题:鉴于这些假设,图书馆可以

  1. 为 Windows .NET 编译或
  2. 在将二进制文件复制到 Mac后,为 MonoTouch 应用程序解决方案直接引用而编译。

基于当前的 Visual Studio 平台和配置?

目前的研究

  1. MonoTouch 解决方案可以使用在 Windows 上编译的可移植库这一事实给了一些希望,即这是可能的。
  2. <NoStdLib>true</NoStdLib> 在为 MonoTouch 构建时在 .csproj 中使用,以及HintPathSystem、System.Core、System.Xml 等的不同 s 似乎是必要的。
  3. 不确定在为 MonoTouch 构建时如何引用正确版本的 mscorlib。
4

2 回答 2

3

事实证明,这在 MSBuild 中是完全可能的。假设您从一个为 Windows .NET 创建的 C# 项目开始,并且还想为 iOS 编译,那么关键点如下。注意:这不适用于 MonoDevelop。它仅适用于 Visual Studio。这是因为 MonoDevelop 目前没有为 MonoTouch 使用成熟的 MSBuild 兼容构建系统。

  1. 为 iOS 创建一个新的解决方案和项目平台,命名为 iOS。这用于为 MonoTouch 编译项目。您可以将其命名为任何您想要的名称,但在下文中始终使用该名称。
  2. 对于 iOS 平台,将 NoStdLib 设置为 true 以避免自动引用 mscorlib.dll。还将路径设置为包含 MonoTouch dll 的本地副本的目录,从 Mac 上的 MonoTouch 安装中复制:

    <PropertyGroup Condition="'$(Platform'=='iOS'">
      <NoStdLib>true</NoStdLib>
      <iOSLibs>c:\MonoTouch\</iOSLibs>
    </PropertyGroup>`
    
  3. 添加对文件夹中所有引用的 MonoTouch 程序集的本地副本的引用:

    <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>
    
  4. Visual Studio 自动添加一个引用所有 .NET 程序集的 ItemGroup。由于我们已经指示 Visual Studio/MSBuild 在为 iOS 构建时从 iOSLibs 文件夹中获取这些,我们应该有条件地禁用默认程序集。这可以阻止 VS 抱怨重复的程序集引用。更改 的第一行ItemGroup并添加条件,如下所示。(注意:程序集列表将根据您的项目当前引用的内容而有所不同。)

    <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>
    

现在你准备好了。为解决方案中的所有项目完成此操作后,您可以从解决方案下拉列表中选择 iOS,并像魔术一样构建 MonoTouch 二进制兼容程序集,而无需使用可移植类库!(这并不意味着 PCL 没有用,它们当然有用,但这里显示的技术更普遍适用。)

更详细地了解 MSBuild 及其强大的功能将帮助您进一步简化,例如:

  1. 将上述大部分内容移动到一个通用的 MSBuild 文件中,您可以从所有项目文件中引用该文件以消除重复。
  2. 使用定义编译器常量<DefineConstants>...</DefineConstants>以允许您的代码根据当前的解决方案和配置以不同的方式做事。
于 2013-02-12T20:59:52.463 回答
1

从技术上讲,应该可以使用https://github.com/jbevain/cecil等工具重写生成的程序集以针对不同的平台,但我认为这不值得(巨大的)努力。拆卸和重建是另一种(昂贵的)选择。

如果您的问题是关于重新定位第三方提供的程序集,而这是您唯一的计划,请确保您没有违反任何许可条款。

现在,如果您可以去掉一些假设,并使用不同的构建系统(如 rake 或 make),您还可以在构建文件级别实现代码共享而无需 PCL。

希望能帮助到你。

于 2013-02-08T08:35:06.187 回答