仅通过属性中的typeof(TypeInAssembly)引用的程序集未被GetReferencedAssemblies()

时间:2016-01-18 13:47:25

标签: c# msbuild .net-assembly roslyn

tl; dr Assembly.GetReferencedAssemblies()似乎不包含仅通过typeof(...)属性中使用的类型引用的程序集,例如通过Visual Studio 2013及更早版本使用MSBuild构建时[SomeAttribute(typeof(TypeInAssembly))],但在Visual Studio 2015中使用Roslyn构建时

这适用于.NET 4.0,4.5和4.6,并且似乎是MSBuild中的错误(?)。有没有办法可靠地获取另一个程序集引用的所有程序集,包括那些仅在属性中通过typeof引用的程序集?

问题的MCVE

重现这一点很简单:在空白C#控制台应用程序项目中引用PresentationCore程序集,并使用以下代码 1,2,3,4

using System;
using System.Reflection;
using System.Windows;

[ReferenceTypeAttribute(typeof(DurationConverter))]
public class Program
{
    static void Main(string[] args)
    {
        // uncomment the following two lines to change the results of GetReferencedAssemblies().
        //Console.WriteLine("DurationConverter assembly from typeof:");
        //showAssemblyNameDetails(typeof(DurationConverter).Assembly.GetName());

        AssemblyName[] referenced = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
        Console.WriteLine(Environment.NewLine + "Referenced Assemblies:");
        foreach ( AssemblyName reference in referenced )
            showAssemblyNameDetails(reference);

        var referenceTypeAttribute = (ReferenceTypeAttribute)typeof(Program)
            .GetCustomAttributes(typeof(ReferenceTypeAttribute), inherit: false)[0];
        AssemblyName presentationCoreAssemblyName = referenceTypeAttribute.Type.Assembly.GetName();
        Console.WriteLine(Environment.NewLine + "DurationConverter Assembly from attribute:");
        showAssemblyNameDetails(presentationCoreAssemblyName);

        Console.ReadKey();
    }

    private static void showAssemblyNameDetails(AssemblyName assemblyName)
    {
        Console.WriteLine("{0} ({1})", assemblyName.Name, assemblyName.Version);
    }
}

ReferenceTypeAttribute的定义是:

public class ReferenceTypeAttribute : Attribute
{
    public readonly Type Type;

    public ReferenceTypeAttribute(Type type)
    {
        Type = type;
    }
}

1 为简洁起见,我已取消namespace并将所有内容放入Main

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

3 我明确地为此编写了自己的属性,而不是使用TypeConverter(这是我的代码中实际使用的属性)来消除任何怀疑.NET在做什么时候做的事情。汇编

4 更改属性以获取object,然后将object转发回Type无效 - 这表明问题已到期到typeof

我的问题

我知道引用但未使用的程序集不包含在GetReferencedAssemblies()的结果中,但为什么未在属性计数中使用?我只能假设这是MSBuild中的一个错误,已在Roslyn中修复,但我找不到任何对此的引用。

我需要为GetReferencedAssemblies()获得可靠的结果,但不希望将明确的引用放在黑客中;通过引用属性的代码 outside 中的类型或其他方式。

完整结果(Visual Studio 2013)

  • 按原样运行代码,输出为:
 
Referenced Assemblies:
mscorlib (4.0.0.0)

DurationConverter Assembly:
PresentationCore (4.0.0.0)

通过使用ILSpy查看程序集来反映这一点:

just mscorlib

请注意,PresentationCore 列为引用的程序集,即使它是通过类的属性引用的,并且解决方案也不会在没有的情况下构建参考。

另请注意,这不受更改目标框架的影响 - 我已经尝试过.NET 4.0,4.5和4.6,但结果是相同的。

  • 只有在Main中取消注释前两行代码,才会引用PresentationCore提取的GetReferencedAssemblies
 
DurationConverter assembly from typeof:
PresentationCore (4.0.0.0)

Referenced Assemblies:
mscorlib (4.0.0.0)
PresentationCore (4.0.0.0)

DurationConverter Assembly from attribute:
PresentationCore (4.0.0.0)

同样,通过查看ILSpy的程序集来反映这一点:

with PresentationCore

完整结果(Visual Studio 2015)

  • PresentationCoreGetReferencedAssemblies的引用,即使这些行已被注释掉,也是如此:
 
Referenced Assemblies:
mscorlib (4.0.0.0)
PresentationCore (4.0.0.0)

DurationConverter Assembly from attribute:
PresentationCore (4.0.0.0)

ILSpy同意:

with PresentationCore

  • 正如预期的那样,取消对前两行的修改并不会改变GetReferencedAssemblies的结果:
 
DurationConverter assembly from typeof:
PresentationCore (4.0.0.0)

Referenced Assemblies:
mscorlib (4.0.0.0)
PresentationCore (4.0.0.0)

DurationConverter Assembly from attribute:
PresentationCore (4.0.0.0)

同样,ILSpy同意:

with PresentationCore

0 个答案:

没有答案