2009-06-07 7 views
11

Comment puis-je déterminer par réflexion si le type d'un objet est défini par une classe dans mon propre assembly ou par le .NET Framework?Détecter si le type d'un objet est un type défini par .NET Framework

Je ne veux pas fournir le nom de mon propre assembly dans le code, car il devrait fonctionner avec n'importe quel assembly et namespace.

+2

point mineur - mais il ne peut être ni votre propre ni Microsoft ... –

Répondre

17

Où les types tiers devraient-ils entrer? Vous pouvez faire la différence entre les types qui prétendent être fournis par Microsoft et les types qui ne le sont pas.

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

Bien sûr, tout type pourrait réclamation être un Microsoft un donné ce schéma, mais si vous êtes en train de ne va l'appeler sur vos propres types et les cadres, je soupçonne que cela fonctionne bien .

Vous pouvez également utiliser le jeton de clé publique de l'assembly. Cela risque d'être plus difficile à simuler. Il s'appuie sur Microsoft en utilisant une clé publique commune pour tous leurs assemblages, ce qu'ils ne font pas (selon le commentaire de Mehrdad ci-dessous). Cependant, vous pouvez facilement adapter cette solution pour un défini des clés publiques acceptées "ceci vient de Microsoft". combiner Peut-être les deux approches en quelque sorte et signaler les différences pour une inspection plus poussée ...

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; 
} 
+0

Tous les assemblys Microsoft n'ont pas le même jeton de clé publique (même maintenant). –

+0

Ick. Mettra à jour la réponse. –

+0

ne peut pas convertir l'octet [] publicKeyToken en chaîne en utilisant AsciiEncoding ou UnicodeEncoding Quel codage est utilisé ou comment obtenir une représentation sous forme de chaîne de PublicKeyToken – Kumar

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

vérifie si le type est déclaré dans l'ensemble courant.

8

Similaire à la réponse de Mehrdad, mais permet la même vérification même si le code est en cours d'exécution dans une autre application.

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

+1 Ceci est une approche intelligente. – user7116

11

Sur la base de la réponse de Jon et le commentaire de Mehrdad, il semble que les trois valeurs suivantes sont utilisées pour le jeton de clé publique (de AssemblyName.FullName) pour les assemblages .NET Framework fourni par .NET 2.0 et plus tard:

PublicKeyToken = b77a5c561934e089

  • mscorlib
  • System.Data
  • System.Data.OracleClient
  • System.Data.SqlXml
  • Système
  • System.Runtime.Remoting
  • System.Transactions
  • System.Windows.Forms
  • système .Xml
  • SMDiagnostics
  • System.Runtime.Serialization
  • System.ServiceModel
  • System.ServiceModel.Install
  • System.ServiceModel.WasHosting

PublicKeyToken = b03f5f7f11d50a3a

  • accessibilité
  • AspNetMMCExt
  • cscompmgd
  • CustomMarshalers
  • 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
  • sysglobl
  • System.Configuration
  • System.Configuration.Install
  • System.Deployment
  • System.Design
  • System.DirectoryServices
  • System.DirectoryServices.Protocols
  • System.Drawing.Design
  • System.Drawing
  • System.EnterpriseServices
  • système .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
  • Sentinel.v3. 5Client

PublicKeyToken = 31bf3856ad364e35

  • PresentationCFFRasterizer
  • PresentationUI

Cela a été généré à partir du code suivant:

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

Juste ce que le docteur a ordonné. – Nathan

Questions connexes