【发布时间】:2009-06-07 19:38:32
【问题描述】:
如何通过反射确定对象的类型是由我自己程序集中的类定义还是由 .NET Framework 定义?
我不想在代码中提供我自己的程序集的名称,因为它应该适用于任何程序集和命名空间。
【问题讨论】:
-
次要 - 但它可能既不是你自己的也不是微软的......
标签: c# .net reflection
如何通过反射确定对象的类型是由我自己程序集中的类定义还是由 .NET Framework 定义?
我不想在代码中提供我自己的程序集的名称,因为它应该适用于任何程序集和命名空间。
【问题讨论】:
标签: c# .net reflection
第三方类型会在哪里出现?您可能想要区分声称由 Microsoft 提供的类型和不提供的类型。
using System;
using System.Linq;
using System.Reflection;
class Test
{
static void Main()
{
Console.WriteLine(IsMicrosoftType(typeof(string)));
Console.WriteLine(IsMicrosoftType(typeof(Test)));
}
static bool IsMicrosoftType(Type type)
{
object[] attrs = type.Assembly.GetCustomAttributes
(typeof(AssemblyCompanyAttribute), false);
return attrs.OfType<AssemblyCompanyAttribute>()
.Any(attr => attr.Company == "Microsoft Corporation");
}
}
当然,考虑到这种方案,任何类型都可以声称是 Microsoft 的,但如果你实际上只打算在你自己的类型和框架类型上调用它,我怀疑这应该可行很好。
或者,您可以使用程序集的公钥令牌。这可能更难伪造。它依赖于 Microsoft 为其所有程序集使用公共公钥,而他们没有(根据 Mehrdad 在下面的评论)。但是,您可以轻松地将此解决方案调整为 set 已接受的“这是来自 Microsoft”的公钥。也许以某种方式结合这两种方法并报告任何差异以供进一步检查......
static bool IsMicrosoftType(Type type)
{
AssemblyName name = type.Assembly.GetName();
byte[] publicKeyToken = name.GetPublicKeyToken();
return publicKeyToken != null
&& publicKeyToken.Length == 8
&& publicKeyToken[0] == 0xb7
&& publicKeyToken[1] == 0x7a
&& publicKeyToken[2] == 0x5c
&& publicKeyToken[3] == 0x56
&& publicKeyToken[4] == 0x19
&& publicKeyToken[5] == 0x34
&& publicKeyToken[6] == 0xe0
&& publicKeyToken[7] == 0x89;
}
【讨论】:
根据 Jon 的回答和 Mehrdad 的评论,以下三个值似乎用于 .NET Framework 提供的来自 .NET 2.0 及更高版本的程序集的公钥令牌(来自 AssemblyName.FullName):
PublicKeyToken=b77a5c561934e089
PublicKeyToken=b03f5f7f11d50a3a
PublicKeyToken=31bf3856ad364e35
这是从以下代码生成的:
private void PrintAssemblyInfo(string fullName)
{
string[] parts = fullName.Split(',');
Console.WriteLine(" - {0}, {1}", parts[0], parts[3]);
}
private void GenerateInfo(string path)
{
foreach (var file in Directory.GetFiles(path,
"*.dll",
SearchOption.AllDirectories))
{
try
{
Assembly assembly = Assembly.ReflectionOnlyLoadFrom(file);
PrintAssemblyInfo(assembly.GetName().FullName);
}
catch { }
}
}
private void GenerateInfo()
{
GenerateInfo(@"C:\Windows\Microsoft.NET\Framework\v2.0.50727");
GenerateInfo(@"C:\Windows\Microsoft.NET\Framework\v3.0");
GenerateInfo(@"C:\Windows\Microsoft.NET\Framework\v3.5");
}
【讨论】:
类似于 Mehrdad 的回答,但即使代码正在其他应用程序中执行,也允许进行相同的检查。
obj.GetType().Assembly == typeof(SomeTypeYouKnowIsInYourAssembly).Assembly
【讨论】:
obj.GetType().Assembly == System.Reflection.Assembly.GetExecutingAssembly()
检查类型是否在当前程序集中声明。
【讨论】: