2009-06-07 17 views
11

¿Cómo puedo determinar por reflexión si el tipo de un objeto está definido por una clase en mi propio ensamblado o por .NET Framework?Detectar si el tipo de un objeto es un tipo definido por .NET Framework

No deseo proporcionar el nombre de mi propio ensamblado en el código, porque debería funcionar con cualquier ensamblado y espacio de nombres.

+2

Un pequeño punto - pero podría ser ni su propio ni Microsoft ... –

Respuesta

17

¿Dónde entrarían los tipos de terceros? Es posible que desee diferenciar entre los tipos que dicen ser provistos por Microsoft y los que no.

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

Por supuesto, cualquier tipo de reclamo podría a ser un complemento de Microsoft que se da este esquema, pero si lo que en realidad sólo va a llamar en sus propios tipos y los marcos, sospecho que esto debería funcionar bien .

Como alternativa, puede usar el token de clave pública del conjunto. Es probable que sea más difícil de falsificar. Confía en que Microsoft use una clave pública común para todas sus asambleas, y no lo hacen (de acuerdo con el comentario de Mehrdad más abajo). Sin embargo, podría adaptar fácilmente esta solución para un conjunto de claves públicas "esto es de Microsoft". Tal vez combinar los dos enfoques de alguna manera y reportar cualquier diferencia para una inspección adicional ...

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

No todos los ensamblados de Microsoft tienen el mismo token de clave pública (incluso ahora). –

+0

Ick. Actualizará la respuesta. –

+0

no se puede convertir el byte [] publicKeyToken en una cadena usando AsciiEncoding o UnicodeEncoding Qué codificación se usa o cómo obtener una representación de cadena del PublicKeyToken – Kumar

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

Comprueba si el tipo está declarado en el ensamblaje actual.

8

Similar a la respuesta de Mehrdad, pero permite la misma comprobación incluso si el código se está ejecutando en alguna otra aplicación.

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

1 Este es un enfoque inteligente. – user7116

11

Sobre la base de la respuesta de Jon y el comentario de Mehrdad, parece que los tres valores siguientes son usados ​​para el símbolo de clave pública (de AssemblyName.FullName) para .NET Framework conjuntos proporcionados desde .NET 2.0 y posterior:

PublicKeyToken = b77a5c561934e089

  • mscorlib
  • System.Data
  • System.Data.OracleClient
  • System.Data.SqlXml
  • Sistema
  • System.Runtime.Remoting
  • System.Transactions
  • System.Windows.Forms
  • Sistema .xml
  • SMDiagnostics
  • System.Runtime.Serialization
  • System.ServiceModel
  • System.ServiceModel.Install
  • System.ServiceModel.WasHosting

PublicKeyToken = b03f5f7f11d50a3a

  • Accesibilidad
  • 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
  • del sistema . Gestión
  • 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

Esto se generó a partir del siguiente código:

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

Justo lo que ordenó el médico. – Nathan

Cuestiones relacionadas