C# 仅通过属性中的typeof(TypeInAssembly)引用的程序集未被GetReferencedAssembly()列为引用

C# 仅通过属性中的typeof(TypeInAssembly)引用的程序集未被GetReferencedAssembly()列为引用,c#,msbuild,.net-assembly,roslyn,C#,Msbuild,.net Assembly,Roslyn,tl;dr:在通过Visual Studio 2013和更早版本使用MSBuild构建时,似乎不包括仅通过属性中使用的类型引用的程序集,typeof(…),例如[SomeAttribute(typeof(TypeInAssembly))],但在Visual Studio 2015中使用Roslyn构建时确实如此 这在.NET4.0、4.5和4.6中都会发生,似乎是MSBuild中的一个bug(?)。是否有任何方法可以可靠地获取其他程序集引用的所有程序集,包括那些仅通过属性中的typeof引用的程

tl;dr:在通过Visual Studio 2013和更早版本使用MSBuild构建时,似乎不包括仅通过属性中使用的类型引用的程序集,
typeof(…)
,例如
[SomeAttribute(typeof(TypeInAssembly))]
,但在Visual Studio 2015中使用Roslyn构建时确实如此

这在.NET4.0、4.5和4.6中都会发生,似乎是MSBuild中的一个bug(?)。是否有任何方法可以可靠地获取其他程序集引用的所有程序集,包括那些仅通过属性中的
typeof
引用的程序集


问题的关键 复制这一点很简单:在空白的C#console应用程序项目中引用
PresentationCore
程序集,并使用以下代码1、2、3、4:

使用系统;
运用系统反思;
使用System.Windows;
[ReferenceTypeAttribute(typeof(DurationConverter))]
公共课程
{
静态void Main(字符串[]参数)
{
//取消对以下两行的注释以更改GetReferencedAssemblys()的结果。
//Console.WriteLine(“DurationConverter assembly from typeof:”);
//showAssemblyNameDetails(typeof(DurationConverter.Assembly.GetName());
AssemblyName[]引用=Assembly.GetExecutionGassembly().GetReferencedAssemblys();
Console.WriteLine(Environment.NewLine+“引用的程序集:”);
foreach(引用中的AssemblyName引用)
showAssemblyNameDetails(参考);
var referenceTypeAttribute=(referenceTypeAttribute)typeof(程序)
.GetCustomAttributes(typeof(ReferenceTypeAttribute),inherit:false)[0];
AssemblyName PresentationRecombulyName=referenceTypeAttribute.Type.Assembly.GetName();
Console.WriteLine(Environment.NewLine+“DurationConverter程序集来自属性:”);
ShowAssemblyName详细信息(PresentationReconombolyName);
Console.ReadKey();
}
私有静态无效ShowAssemblyName详细信息(AssemblyName AssemblyName)
{
Console.WriteLine(“{0}({1})”,assemblyName.Name,assemblyName.Version);
}
}
其中
ReferenceTypeAttribute
的定义为:

公共类引用类型属性:属性
{
公共只读类型;
公共引用类型属性(类型)
{
类型=类型;
}
}
1为了简洁起见,我已经去掉了
名称空间
,将所有内容都放在
Main

2我之所以选择它,是因为它位于默认情况下未添加到C#项目的程序集中(
PresentationCore
)。我试过的每种类型都是一样的

3我明确地为此编写了自己的属性,而不是使用(这是我代码中实际使用的属性)来消除任何关于.NET在编译过程中正在做一些古怪事情的怀疑

4更改属性以获取
对象
,然后将
对象
强制转换回
类型
无效-这表示问题是由
类型
引起的

我的问题 我知道被引用但未使用的程序集不包括在
getReferenceAssemblys()
的结果中,但为什么在属性中不使用呢?我只能假设这是MSBuild中的一个bug,已经在Roslyn中修复,但我找不到任何对此的引用

我需要对
getReferencedAssemblys()
有可靠的结果,但不想把显式引用作为黑客;通过在属性之外的代码中引用类型,或者通过其他方式


完整结果(Visual Studio 2013)
  • 按原样运行代码,输出为:

引用的程序集:
mscorlib(4.0.0.0)
持续时间转换器总成:
演示核心(4.0.0.0)
通过以下方式查看部件可以反映这一点:

请注意,
PresentationCore
未作为引用程序集列出,即使该程序集是通过类上的属性引用的,并且在没有引用的情况下无法生成解决方案

还请注意,更改目标框架不会影响这一点-我尝试过.NET4.0、4.5和4.6,但结果是相同的

  • 只有取消对
    Main
    中前两行代码的注释,
    GetReferencedAssemblys
    才会拾取对
    PresentationCore
    的引用:

DurationConverter组件的类型:
演示核心(4.0.0.0)
引用的程序集:
mscorlib(4.0.0.0)
演示核心(4.0.0.0)
DurationConverter程序集自属性:
演示核心(4.0.0.0)
同样,使用ILSpy查看程序集可以反映这一点:

完整结果(Visual Studio 2015)
  • PresentationCore
    的引用由
    GetReferencedAssemblys
    拾取,即使行被注释掉:

引用的程序集:
mscorlib(4.0.0.0)
演示核心(4.0.0.0)
DurationConverter程序集自属性:
演示核心(4.0.0.0)
ILSpy同意:

  • 正如所料,取消注释前两行不会更改
    getReferenceAssemblys
    的结果:

DurationConverter组件的类型:
演示核心(4.0.0.0)
引用的程序集:
mscorlib(4.0.0.0)
演示核心(4.0.0.0)
DurationConverter程序集自属性:
演示核心(4.0.0.0)
ILSpy再次表示同意:


您是否排除了这是ILSpy问题的可能性?您能用验证您的结果吗?当编译器在程序集元数据中发出
.assembly
指令时,这很好,但这不是必需的。属性构造函数参数非常特殊,很容易看出旧编译器如何无法发出该指令。虫子。F