如何根据所选配置将项目构建为可移植类库或普通类库?

Posted

技术标签:

【中文标题】如何根据所选配置将项目构建为可移植类库或普通类库?【英文标题】:How can a project be built as a portable or a normal class library depending on the selected configuration? 【发布时间】:2016-02-10 19:22:19 【问题描述】:

上下文:我们有一个名为“THEPROJECT”的通用库项目,它与 Xamarin 移动解决方案和 Visual Studio 中的 Web 项目共享。由于 Xamarin 中的限制,此共享库是 PCL Profile259。在我们的 Web 应用程序解决方案中,我们希望使用适当的属性标记数据模型,以便 DataContext 正常工作(因为我们想使用 LinqToSql)。

尝试的解决方案:我们决定研究“THEPROJECT”项目并更改 msbuild,使其能够以可移植库/普通类库的状态存在,具体取决于在 Visual Studio 中选择配置。

我们已经查看了this post 中的解决方案,但这只是解决方案的一部分。我们可以让项目作为一个或另一个存在,但是它需要手动更改项目文件。现在我们收到加载以下项目的错误。可移植项目的 必须是“.NETPortable”。

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <Configuration Condition=" '$(Configuration)' == '' ">DebugDesktop</Configuration>
        <Platform Condition="'$(Platform)' == ''">AnyCPU</Platform>
        <ProjectGuid>426E7BD8-9DA8-4E15-9512-72E7C632B037</ProjectGuid>
        <OutputType>Library</OutputType>
        <AppDesignerFolder>Properties</AppDesignerFolder>
        <RootNamespace>THEPROJECT</RootNamespace>
        <AssemblyName>THEPROJECT</AssemblyName>
        <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
        <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
        <BuildMode>Desktop</BuildMode>
    </PropertyGroup>

    <!-- Define the Build Configurations -->
    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugDesktop|AnyCPU' ">
        <DebugSymbols>true</DebugSymbols>
        <DebugType>full</DebugType>
        <Optimize>false</Optimize>
        <OutputPath>bin\Desktop\Debug\</OutputPath>
        <DefineConstants>TRACE;DEBUG;</DefineConstants>
        <ErrorReport>prompt</ErrorReport>
        <WarningLevel>4</WarningLevel>
        <ConsolePause>false</ConsolePause>
        <BuildMode>Desktop</BuildMode>
    </PropertyGroup>
    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseDesktop|AnyCPU' ">
        <DebugType>pdbonly</DebugType>
        <Optimize>true</Optimize>
        <OutputPath>bin\Desktop\Release\</OutputPath>
        <DefineConstants>TRACE</DefineConstants>
        <ErrorReport>prompt</ErrorReport>
        <WarningLevel>4</WarningLevel>
        <BuildMode>Desktop</BuildMode>
    </PropertyGroup>
    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugPCL|AnyCPU' ">
        <DebugSymbols>true</DebugSymbols>
        <DebugType>full</DebugType>
        <Optimize>false</Optimize>
        <OutputPath>bin\PCL\Debug\</OutputPath>
        <DefineConstants>TRACE;DEBUG;</DefineConstants>
        <ErrorReport>prompt</ErrorReport>
        <WarningLevel>4</WarningLevel>
        <ConsolePause>false</ConsolePause>
        <BuildMode>Portable</BuildMode>
    </PropertyGroup>
    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleasePCL|AnyCPU' ">
        <DebugType>pdbonly</DebugType>
        <Optimize>true</Optimize>
        <OutputPath>bin\PCL\Release\</OutputPath>
        <DefineConstants>TRACE</DefineConstants>
        <ErrorReport>prompt</ErrorReport>
        <WarningLevel>4</WarningLevel>
        <BuildMode>Portable</BuildMode>
    </PropertyGroup>

    <!-- Determine the correct properties for PCL/Desktop -->
    <Choose>
        <When Condition=" '$(BuildMode)' == 'Portable' ">
            <PropertyGroup>
                <ProjectTypeGuids>786C830F-07A1-408B-BD7F-6EE04809D6DB;FAE04EC0-301F-11D3-BF4B-00C04F79EFBC</ProjectTypeGuids>
                <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
                <TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
                <DynamicImportPath>$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets</DynamicImportPath>
            </PropertyGroup>
        </When>
        <When Condition=" '$(BuildMode)' == 'Desktop' ">
            <PropertyGroup>
                <FileAlignment>512</FileAlignment>
                <TargetFrameworkProfile />
                <DynamicImportPath>$(MSBuildToolsPath)\Microsoft.CSharp.targets</DynamicImportPath>
            </PropertyGroup>
            <ItemGroup>
                <Reference Include="System.Data.Linq" />
            </ItemGroup>
        </When>
    </Choose>

    <ItemGroup>
        <Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
            <HintPath>..\..\mobileapplication\packages\Newtonsoft.Json.8.0.2\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
            <Private>True</Private>
        </Reference>
        <Reference Include="System" />
        <Reference Include="System.Core" />
        <Reference Include="System.Xml.Linq" />
        <Reference Include="Microsoft.CSharp" />
        <Reference Include="System.Xml" />
    </ItemGroup>
    <ItemGroup>
        <ProjectReference Include="..\..\sqlite-net-extensions\SQLiteNetExtensions\SQLiteNetExtensions-PCL.csproj">
            <Project>f723017d-ede5-49cc-a84f-881c067c6004</Project>
            <Name>SQLiteNetExtensions-PCL</Name>
        </ProjectReference>
        <ProjectReference Include="..\..\sqlitenetpcl\src\SQLite.Net\SQLite.Net.csproj">
            <Project>4971d437-0694-4297-a8cc-146ce08c3bd9</Project>
            <Name>SQLite.Net</Name>
        </ProjectReference>
    </ItemGroup>

    <Import Project="$(DynamicImportPath)" />

    <!-- Source/Resx etc... -->
</Project>

【问题讨论】:

【参考方案1】:

要回答关于根据配置使项目成为“便携式”或“普通”的问题,当弹出的错误是关于&lt;TargetFrameworkIdentifier&gt; 必须是.NETPortable

从配置中删除所有&lt;ProjectTypeGuids&gt;

那些项目类型 GUID 为 Visual Studio 提供了一些仅与可移植项目有关的 GUI 内容,因此当配置不可移植时,它会导致您遇到错误。但是由于您对编辑 XML 感到很自在,因此您显然不需要这些东西。此外,您可以继续使用 GUI 来编辑项目属性,同时删除项目类型 GUID。

至少从 Visual Studio 2015 开始。

【讨论】:

【参考方案2】:

当您创建可移植类库时,您需要将您的库创建为 Windows 8.1 可移植库,您不能为此使用通用库,这听起来就像您在 Xamarin 的约束下所做的那样。 Windows 8.1 Portable Library 是一种混合库,允许经典 .net 与新的轻量级 .net 版本进行通信。

可移植类库的问题是它不能通过项目引用来引用经典类库,您只能通过 DLL 引用来引用它。如果您对编辑该文件感到不舒服,您不需要弄乱 XML,只需找到已编译的 DLL 并手动添加引用即可。如果您选择这样做,您将需要手动更新构建依赖项,否则您可能有损坏的引用。

问题似乎并不完全在您的 .csproj 中,但也存在于您的 project.json 中。我一直注意到 Visual Studio 没有生成正确的 project.json 文件。我必须修改 UI 中的目标以使其正确生成。一旦我得到初始的 project.json 来生成,我就没有其他问题了。

在做任何事情之前,我们需要连接我们的可移植类库以处理经典类库。第一步是将目标框架从属性更新为目标 .net 4.5 或您喜欢的任何版本。

完成此操作后,确认 project.json 文件如下所示:


  "supports": ,
  "dependencies": ,
  "frameworks": 
    ".NETPortable,Version=v4.5,Profile=Profile259": 
  

一旦您的可移植类库以正确的版本为目标,您就可以将 DLL 引用添加到已编译的 .net 4.5 程序集。我没有对可移植类库的 csproj 文件进行任何其他更改,但这里是其源代码,因此您可以查看。

注意 ClassLibrary1 是如何被引用的:

    <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>7C4EB968-4C17-438C-B981-97EDC865F312</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>PortableLibrary</RootNamespace>
    <AssemblyName>PortableLibrary</AssemblyName>
    <DefaultLanguage>en-US</DefaultLanguage>
    <FileAlignment>512</FileAlignment>
    <ProjectTypeGuids>786C830F-07A1-408B-BD7F-6EE04809D6DB;FAE04EC0-301F-11D3-BF4B-00C04F79EFBC</ProjectTypeGuids>
    <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="Class1.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <Reference Include="ClassLibrary1">
      <HintPath>..\ClassLibrary1\bin\Debug\ClassLibrary1.dll</HintPath>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <None Include="project.json" />
  </ItemGroup>
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

假设您的 Web 项目是 ASP.NET Core 1.0,这应该可以消除问题。如果您正在运行 Classic ASP.NET 应用程序,您可能仍需要创建构建规则。

TLDR:

您的 project.json 文件似乎有问题,请确保它正确生成并且您不能通过项目引用直接引用 .net 4.5,您必须引用 DLL。

【讨论】:

以上是关于如何根据所选配置将项目构建为可移植类库或普通类库?的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 引入自定义类库或第三方类库

可移植类库配置文件 78 缺少属性相关的方法/属性

vs 2013 可移植类库 windows.props 未找到

Visual Studio中类库和可移植类库的区别

为啥我应该在 Xamarin 中使用可移植类库?

将 HttpModule .Net 类库移植到 .Net Core Web API