2010-03-20 24 views
48

Tengo el siguiente método que serializa un objeto a una etiqueta HTML. Solo quiero hacer esto aunque el tipo no sea Anónimo.¿Cómo probar si un tipo es anónimo?

private void MergeTypeDataToTag(object typeData) 
{ 
    if (typeData != null) 
    { 
     Type elementType = typeData.GetType(); 

     if (/* elementType != AnonymousType */) 
     { 
      _tag.Attributes.Add("class", elementType.Name);  
     } 

     // do some more stuff 
    } 
} 

¿Alguien me puede mostrar cómo lograr esto?

Gracias

Respuesta

53

Desde: http://www.liensberger.it/web/blog/?p=191

private static bool CheckIfAnonymousType(Type type) 
{ 
    if (type == null) 
     throw new ArgumentNullException("type"); 

    // HACK: The only way to detect anonymous types right now. 
    return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false) 
     && type.IsGenericType && type.Name.Contains("AnonymousType") 
     && (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$")) 
     && (type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic; 
} 

HTH.

EDIT:
Otro vínculo con el método de extensión: Determining whether a Type is an Anonymous Type

+2

fuente de http://jclaes.blogspot.com/2011/05/checking-for-anonymous-types.html – serhio

+1

Lamentablemente esto es falso para 'new {}. GetType()' Pero creo que '&& type. IsGenericType' puede salvarse de forma segura. –

+2

Parece que necesita '(type.Name.Contains (" AnonymousType ") || type.Name.Contains (" AnonType "))' para ser compatible con Mono. Fuente: [Método de extensión de NancyFx] (https://github.com/NancyFx/Nancy/blob/master/src/Nancy/ViewEngines/Extensions.cs) –

5

Comprobar si CompilerGeneratedAttribute y DebuggerDisplayAttribute.Type

aquí es el código generado por el compilador para un tipo de anomymous

[CompilerGenerated, DebuggerDisplay(@"\{ a = {a} }", Type="<Anonymous Type>")] 
internal sealed class <>f__AnonymousType0<<a>j__TPar> 
{ 
... 
} 
+2

Solo funciona cuando se compila en modo de depuración. –

+0

Funciona en modo de lanzamiento también !. var anonType = new {a = 1, b = 2} .GetType(); anonType.CustomAttributes.Select (e => e.AttributeType) .Should(). Contain (typeof (CompilerGeneratedAttribute)); –

12

rápida y sucia:

if(obj.GetType().Name.Contains("AnonymousType")) 
+3

Estoy muy tentado de hacer clic en +1. No debe hacer clic !! xD –

+1

Desafortunadamente desagradable y lento. –

6

Pues bien, hoy compiier genera tipos anónimos como clases genéricas y sellado. Una combinación paradójica ya que la especialización de una clase genérica es un tipo de herencia, ¿no es así? Para que pueda verificar esto: 1. ¿Es este un tipo genérico? Sí => 2) ¿está su definición sellada & & no es pública? Sí => 3) ¿su definición tiene el atributo CompilerGeneratedAttribute? Supongo que si estos 3 criterios son ciertos, tenemos un tipo anónimo ... Bueno ... Existe un problema con CUALQUIERA de los métodos descritos: son aspectos de uso que pueden cambiar en las próximas versiones de .NET y será así hasta que Microsoft agregue la propiedad booleana IsAnonymous a la clase Type. Espero que va a pasar antes de que todos morimos ... Hasta ese día, se puede comprobar de esta manera:

using System.Runtime.CompilerServices; 
using System.Reflection; 

public static class AnonymousTypesSupport 
{ 
    public static bool IsAnonymous(this Type type) 
    { 
     if (type.IsGenericType) 
     { 
      var d = type.GetGenericTypeDefinition(); 
      if (d.IsClass && d.IsSealed && d.Attributes.HasFlag(TypeAttributes.NotPublic)) 
      { 
       var attributes = d.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false); 
       if (attributes != null && attributes.Length > 0) 
       { 
        //WOW! We have an anonymous type!!! 
        return true; 
       } 
      } 
     } 
     return false; 
    } 

    public static bool IsAnonymousType<T>(this T instance) 
    { 
     return IsAnonymous(instance.GetType()); 
    } 
} 
8

simplemente puede comprobar si el espacio de nombres es nulo.

public static bool IsAnonymousType(this object instance) 
{ 

    if (instance==null) 
     return false; 

    return instance.GetType().Namespace == null; 
} 
+1

¿Esto funciona para mono? – albertjan

+0

Hay casos en que esto no es cierto. No estoy seguro de todos los casos donde esto falla, pero un ejemplo es cuando una expresión lambda se usa dentro de un método concreto protegido de una clase abstracta con parámetros genéricos. Estoy seguro de que hay casos más simples que también fallarían. – Nathan

+1

Nunca he visto que esto falle y creo que esto se usa en SimpleData para la detección anónima. Proporcione un ejemplo de código donde esto realmente falla. – DalSoft

Cuestiones relacionadas