【问题标题】:Detect if the type of an object is a type defined by .NET Framework检测对象的类型是否为 .NET Framework 定义的类型
【发布时间】:2009-06-07 19:38:32
【问题描述】:

如何通过反射确定对象的类型是由我自己程序集中的类定义还是由 .NET Framework 定义?

我不想在代码中提供我自己的程序集的名称,因为它应该适用于任何程序集和命名空间。

【问题讨论】:

  • 次要 - 但它可能既不是你自己的也不是微软的......

标签: c# .net reflection


【解决方案1】:

第三方类型会在哪里出现?您可能想要区分声称由 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;
}

【讨论】:

  • 并非所有 Microsoft 程序集都具有相同的公钥令牌(即使是现在)。
  • 无法使用 AsciiEncoding 或 UnicodeEncoding 将 byte[] publicKeyToken 转换为字符串 使用什么编码或如何获取 PublicKeyToken 的字符串表示
  • BitConverter.ToString(bytes) 会给你十六进制。
  • 如果您想在 BitConverter 版本和程序集全名之间进行字符串比较,您需要添加以下内容或等效项,因为 BitConverter 对值的格式不同:BitConverter.ToString(asmName .GetPublicKeyToken()).Replace("-","").ToLower()
【解决方案2】:

根据 Jon 的回答和 Mehrdad 的评论,以下三个值似乎用于 .NET Framework 提供的来自 .NET 2.0 及更高版本的程序集的公钥令牌(来自 AssemblyName.FullName):

PublicKeyToken=b77a5c561934e089

  • mscorlib
  • System.Data
  • System.Data.OracleClient
  • System.Data.SqlXml
  • 系统
  • System.Runtime.Remoting
  • System.Transactions
  • System.Windows.Forms
  • System.Xml
  • SM 诊断
  • System.Runtime.Serialization
  • System.ServiceModel
  • System.ServiceModel.Install
  • System.ServiceModel.WasHosting

PublicKeyToken=b03f5f7f11d50a3a

  • 辅助功能
  • AspNetMMCExt
  • cscompmgd
  • 自定义编组器
  • IEExecRemote
  • IEHost
  • IIEHost
  • ISymWrapper
  • Microsoft.Build.Conversion
  • Microsoft.Build.Engine
  • Microsoft.Build.Framework
  • Microsoft.Build.Tasks
  • Microsoft.Build.Utilities
  • Microsoft.JScript
  • Microsoft.VisualBasic.Compatibility.Data
  • Microsoft.VisualBasic.Compatibility
  • Microsoft.VisualBasic
  • Microsoft.VisualBasic.Vsa
  • Microsoft.VisualC
  • Microsoft.Vsa
  • Microsoft.Vsa.Vb.CodeDOMProcessor
  • Microsoft_VsaVb
  • 系统全局
  • 系统配置
  • System.Configuration.Install
  • System.Deployment
  • System.Design
  • System.DirectoryServices
  • System.DirectoryServices.Protocols
  • System.Drawing.Design
  • System.Drawing
  • System.EnterpriseServices
  • 系统管理
  • System.Messaging
  • System.Runtime.Serialization.Formatters.Soap
  • 系统安全
  • System.ServiceProcess
  • System.Web
  • System.Web.Mobile
  • System.Web.RegularExpressions
  • System.Web.Services
  • Microsoft.Transactions.Bridge
  • Microsoft.Transactions.Bridge.Dtc
  • Microsoft.Build.Tasks.v3.5
  • Microsoft.CompactFramework.Build.Tasks
  • Microsoft.Data.Entity.Build.Tasks
  • Microsoft.VisualC.STLCLR
  • Sentinel.v3.5Client

PublicKeyToken=31bf3856ad364e35

  • PresentationCFFRasterizer
  • 演示界面

这是从以下代码生成的:

    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");
    }

【讨论】:

  • 正是医生所要求的。
【解决方案3】:

类似于 Mehrdad 的回答,但即使代码正在其他应用程序中执行,也允许进行相同的检查。

obj.GetType().Assembly == typeof(SomeTypeYouKnowIsInYourAssembly).Assembly

【讨论】:

    【解决方案4】:
    obj.GetType().Assembly == System.Reflection.Assembly.GetExecutingAssembly()
    

    检查类型是否在当前程序集中声明。

    【讨论】:

      猜你喜欢
      • 2022-01-25
      • 2011-09-26
      • 2016-05-28
      • 1970-01-01
      • 2014-08-22
      • 2022-11-12
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      相关资源
      最近更新 更多