Определить, является ли тип объекта типом, определенным в .NET Framework - PullRequest
12 голосов
/ 07 июня 2009

Как по рефлексии определить, определен ли тип объекта классом в моей сборке или .NET Framework?

Я не хочу указывать имя своей сборки в коде, потому что она должна работать с любой сборкой и пространством имен.

Ответы [ 4 ]

17 голосов
/ 07 июня 2009

Откуда придут сторонние типы? Возможно, вы захотите провести различие между типами, которые, как утверждают, предоставляются 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 использует общий открытый ключ для всех своих сборок, чего они не делают (согласно комментарию Мехрдада ниже). Однако вы можете легко адаптировать это решение для набора принятых открытых ключей «это от 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;
}
11 голосов
/ 04 августа 2009

Исходя из ответа Джона и комментария Мехрада, представляется, что следующие три значения используются для токена открытого ключа (из AssemblyName.FullName) для сборок .NET Framework, предоставленных сборками из .NET 2.0 и более поздних версий:

PublicKeyToken = b77a5c561934e089

  • mscorlib
  • System.Data
  • System.Data.OracleClient
  • System.Data.SqlXml
  • Система
  • system.runtime.remoting
  • System.Transactions
  • System.Windows.Forms
  • System.Xml
  • SMDiagnostics
  • System.Runtime.Serialization
  • System.ServiceModel
  • System.ServiceModel.Install
  • System.ServiceModel.WasHosting

PublicKeyToken = b03f5f7f11d50a3a

  • Доступность
  • AspNetMMCExt
  • cscompmgd
  • CustomMarshalers
  • 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
  • sysglobl
  • 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.Build.Tasks.v3.5
  • Microsoft.CompactFramework.Build.Tasks
  • Microsoft.Data.Entity.Build.Tasks
  • Microsoft.VisualC.STLCLR

PublicKeyToken = 31bf3856ad364e35

  • PresentationCFFRasterizer
  • PresentationUI

Это было сгенерировано из следующего кода:

    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");
    }
8 голосов
/ 07 июня 2009

Аналогично ответу Мерадада, но допускает такую ​​же проверку, даже если код выполняется в каком-то другом приложении.

obj.GetType().Assembly == typeof(SomeTypeYouKnowIsInYourAssembly).Assembly
7 голосов
/ 07 июня 2009
obj.GetType().Assembly == System.Reflection.Assembly.GetExecutingAssembly()

Проверяет, объявлен ли тип в текущей сборке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...