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
引用的程序集?
重现这一点很简单:在空白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 中的类型或其他方式。
Referenced Assemblies: mscorlib (4.0.0.0) DurationConverter Assembly: PresentationCore (4.0.0.0)
通过使用ILSpy查看程序集来反映这一点:
请注意,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的程序集来反映这一点:
PresentationCore
对GetReferencedAssemblies
的引用,即使这些行已被注释掉,也是如此:Referenced Assemblies: mscorlib (4.0.0.0) PresentationCore (4.0.0.0) DurationConverter Assembly from attribute: PresentationCore (4.0.0.0)
ILSpy同意:
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同意: