检测对象的类型是否为.NET Framework定义的类型

k3bvogb1  于 2022-11-26  发布在  .NET
关注(0)|答案(5)|浏览(137)

如何通过反射确定对象的类型是由我自己的程序集中的类定义的还是由.NET Framework定义的?
我不想在代码中提供我自己的程序集的名称,因为它应该与任何程序集和命名空间一起工作。

xqnpmsa8

xqnpmsa81#

第三方类型将从何而来?您可能希望区分声称由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在下面的评论)。然而,您可以轻松地将此解决方案用于一组可接受的“This is from 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;
}
u7up0aaq

u7up0aaq2#

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

公钥令牌=b77a5c561934e089

  • 姆斯科尔利布
  • 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
    公钥令牌=b03f5f7f11d50a3a
  • 可访问性
  • AspNetMMC扩展
  • 复合
  • 自订封送处理器
  • IEExecRemote(远程执行)
  • IE主机
  • IIE主机
  • 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
  • 微软_VsaVb
  • 系统球
  • System.Configuration
  • System.Configuration.Install
  • System.Deployment
  • System.Design
  • System.DirectoryServices
  • System.DirectoryServices.Protocols
  • System.Drawing.Design
  • System.Drawing
  • System.EnterpriseServices
  • System.Management
  • System.Messaging
  • System.Runtime.Serialization.Formatters.Soap
  • System.Security
  • System.ServiceProcess
  • System.Web
  • System.Web.Mobile
  • System.Web.RegularExpressions
  • System.Web.Services
  • Microsoft.Transactions.Bridge
  • Microsoft.Transactions.Bridge.Dtc
  • Microsoft.生成.任务.v3.5
  • Microsoft.CompactFramework.Build.Tasks
  • Microsoft.Data.Entity.Build.Tasks
  • Microsoft.VisualC.STLCLR
  • Sentinel.v3.5Client
    公钥令牌=31bf3856ad364e35
  • 演示文稿CFFR星号
  • 演示UI

这是从下列程式码产生的:

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

jecbmhm33#

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

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

i7uq4tfw4#

obj.GetType().Assembly == System.Reflection.Assembly.GetExecutingAssembly()

检查型别是否已在目前组件中宣告。

guz6ccqo

guz6ccqo5#

下面是一个更现代的、大约2022年版本的Scott Dorman的解决方案,它给出了公钥令牌的最终列表:

using System.Reflection;

new PublicKeyExplorer().GenerateInfo();

class PublicKeyExplorer
{
private string GetPublicKeyToken(string fullName)
{
    string[] parts = fullName.Split(',');
    return parts[3];
}

private void GenerateInfo(string path, HashSet<string> tokens)
{
    foreach (var file in Directory.GetFiles(path,
                 "*.dll",
                 SearchOption.AllDirectories))
    {
        try
        {
            Assembly assembly = Assembly.LoadFrom(file);
            tokens.Add(GetPublicKeyToken(assembly.GetName().FullName));
        }
        catch (Exception e)
        {
        }
    }
}

public void GenerateInfo()
{
    var tokens = new HashSet<string>();
    GenerateInfo(@"C:\Program Files\dotnet\sdk\3.1.425\", tokens);
    GenerateInfo(@"C:\Program Files\dotnet\sdk\5.0.408\", tokens);
    GenerateInfo(@"C:\Program Files\dotnet\sdk\6.0.401\", tokens);
    GenerateInfo(@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\", tokens);
    GenerateInfo(@"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\", tokens);

    foreach (var publicKeyToken in tokens)
    {
        Console.WriteLine(publicKeyToken);
    }
}

}

相关问题