指定输入的 C# 编译器选项

以下选项控制编译器输入。 新的 MSBuild 语法以粗体显示。 旧的 csc.exe 语法以 code style 显示。

  • 引用 / -reference-references:引用指定程序集文件或文件中的元数据。
  • AddModules / -addmodule:添加模块(使用 target:module 此程序集创建)。
  • EmbedInteropTypes / -link:从指定的互作程序集文件中嵌入元数据。

参考文献

“引用”选项使编译器将指定文件中的公共类型信息导入到当前项目中,使你能够引用指定程序集文件中的元数据。

<Reference Include="filename" />

filename 是包含程序集清单的文件的名称。 若要导入多个文件,请为每个文件包含单独的 Reference 元素。 可以将别名定义为 Reference 元素的子元素:

<Reference Include="filename.dll">
  <Aliases>LS</Aliases>
</Reference>

在前面的示例中, LS 是表示将 包含程序集filename.dll中所有命名空间的根命名空间的有效 C# 标识符。 导入的文件必须包含清单。 使用 AdditionalLibPaths 指定一个或多个程序集引用所在的目录。 AdditionalLibPaths 主题还讨论了编译器在其中搜索程序集的目录。 为了使编译器能够识别程序集中的类型,而不是在模块中,需要强制解析类型,可以通过定义类型的实例来解析该类型。 还有其他方法可以解析编译器的程序集中的类型名称:例如,如果继承自程序集中的类型,则类型名称将由编译器识别。 有时,必须从一个程序集中引用同一组件的两个不同版本。 为此,请对每个文件的 References 元素使用 Aliases 元素来区分这两个文件。 此别名将用作组件名称的限定符,并将解析为其中一个文件中的组件。

注释

在 Visual Studio 中,使用 “添加引用” 命令。 有关详细信息,请参阅 如何:使用引用管理器添加或删除引用

AddModules

此选项将使用开关创建的 <TargetType>module</TargetType> 模块添加到当前编译:

<AddModule Include=file1 />
<AddModule Include=file2 />

其中 filefile2 是包含元数据的输出文件。 该文件不能包含程序集清单。 若要导入多个文件,请使用逗号或分号分隔文件名。 使用 AddModules 添加的所有模块必须在运行时与输出文件位于同一目录中。 也就是说,可以在编译时在任何目录中指定模块,但该模块必须在运行时位于应用程序目录中。 如果模块在运行时不在应用程序目录中,你将获得一个 TypeLoadExceptionfile 不能包含程序集。 例如,如果输出文件是使用 Module 的 TargetType 选项创建的,则可以使用 AddModules 导入其元数据。

如果输出文件是使用模块以外的 TargetType 选项创建的,则不能使用 AddModules 导入其元数据,但可以使用“引用”选项导入。

EmbedInteropTypes

使编译器使指定程序集中的 COM 类型信息可用于当前正在编译的项目。

<References>
  <EmbedInteropTypes>file1;file2;file3</EmbedInteropTypes>
</References>

其中 file1;file2;file3 以分号分隔的程序集文件名列表。 如果文件名包含空格,请将名称用引号引起来。 通过 EmbedInteropTypes 选项,可以部署具有嵌入类型信息的应用程序。 然后,应用程序可以使用运行时程序集中的类型来实现嵌入类型信息,而无需引用运行时程序集。 如果发布各种版本的运行时程序集,则包含嵌入类型信息的应用程序可以处理各种版本,而无需重新编译。 有关示例,请参阅 演练:从托管程序集嵌入类型

使用 EmbedInteropTypes 选项在处理 COM 互作时特别有用。 可以嵌入 COM 类型,以便应用程序不再需要目标计算机上的主互作程序集 (PIA)。 EmbedInteropTypes 选项指示编译器将引用互作程序集中的 COM 类型信息嵌入生成的已编译代码中。 COM 类型由 CLSID (GUID) 值标识。 因此,应用程序可以在安装了具有相同 CLSID 值的相同 COM 类型的目标计算机上运行。 自动Microsoft Office 的应用程序是一个很好的示例。 由于 Office 等应用程序通常在不同的版本中保留相同的 CLSID 值,因此应用程序可以使用引用的 COM 类型,前提是目标计算机上安装了 .NET Framework 4 或更高版本,并且应用程序使用引用的 COM 类型中包含的方法、属性或事件。 EmbedInteropTypes 选项仅嵌入接口、结构和委托。 不支持嵌入 COM 类。

注释

在代码中创建嵌入式 COM 类型的实例时,必须使用相应的接口创建实例。 尝试使用 CoClass 创建嵌入 COM 类型的实例会导致错误。

引用 编译器选项一样, EmbedInteropTypes 编译器选项使用 Csc.rsp 响应文件,该文件引用经常使用的 .NET 程序集。 如果不希望编译器使用 Csc.rsp 文件,请使用 NoConfig 编译器选项。

// The following code causes an error if ISampleInterface is an embedded interop type.
ISampleInterface<SampleType> sample;

如果类型来自外部程序集,则不能使用具有从互作程序集嵌入其类型的泛型参数的类型。 此限制不适用于接口。 例如,请考虑 Range 程序集 Microsoft.Office.Interop.Excel 中定义的接口。 如果库嵌入程序集中的 Microsoft.Office.Interop.Excel 互作类型,并公开一个返回具有类型为 Range 接口的参数的泛型类型的方法,则该方法必须返回泛型接口,如以下代码示例所示。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Interop.Excel;

public class Utility
{
    // The following code causes an error when called by a client assembly.
    public List<Range> GetRange1()
    {
        return null;
    }

    // The following code is valid for calls from a client assembly.
    public IList<Range> GetRange2()
    {
        return null;
    }
}

在下面的示例中,客户端代码可以调用返回 IList 泛型接口的方法,而不会出错。

public class Client
{
    public void Main()
    {
        Utility util = new Utility();

        // The following code causes an error.
        List<Range> rangeList1 = util.GetRange1();

        // The following code is valid.
        List<Range> rangeList2 = (List<Range>)util.GetRange2();
    }
}