2008-11-24 12 views
22

¿Hay algo para usar, para determinar si un tipo es realmente de tipo anónimo? Por ejemplo, una interfaz, etc.Tipos anónimos - ¿Hay alguna característica de distinción?

El objetivo es crear algo como lo siguiente ...

//defined like... 
public static T Get<T>(this IAnonymous obj, string prop) { 
    return (T)obj.GetType().GetProperty(prop).GetValue(obj, null); 
} 
//... 

//And then used like... 
var something = new { name = "John", age = 25 }; 
int age = something.Get<int>("age"); 

O es que sólo la belleza de un tipo anónimo? ¿Nada para identificarse porque toma una nueva forma?

Nota - Soy consciente de que puede escribir un método de extensión para el objeto clase , pero que parece como un poco exagerado, en mi opinión.

Respuesta

48

EDITAR: La siguiente lista se aplica a los tipos anónimos de C#. VB.NET tiene reglas diferentes, en particular, puede generar tipos anónimos mutables (y lo hace de forma predeterminada). Jared ha señalado en el comentario que el estilo de nombre es diferente también. Básicamente esto es bastante frágil ...

No se puede identificar en una limitación genérica, pero:

  • Será una clase (en lugar de la interfaz, enumeración, estructura, etc.)
  • tendrá la CompilerGeneratedAttribute que se le aplica
  • se anulará iguales, GetHashCode y ToString
  • será en el espacio de nombres global
  • no se pueden anidar en otro tipo
  • Será interna
  • Se selló
  • Será derivan directamente de object
  • Será genérico con tantos parámetros de tipo como propiedades. (Usted puede tener un tipo anónimo no genérico, sin propiedades. Sin embargo, es un poco inútil.)
  • Cada propiedad tendrá un parámetro de tipo con un nombre que incluye el nombre de la propiedad, y será de ese parámetro de tipo, p. Ej. Nombre de la propiedad se convierte en una propiedad de tipo <> _NAME
  • Cada propiedad será de sólo lectura pública y
  • Para cada propiedad no será un campo de sólo lectura privada correspondiente
  • No habrá otras propiedades o campos
  • Habrá un constructor que tomará un parámetro correspondiente a cada parámetro de tipo, en el mismo orden que los parámetros de tipo
  • Cada método y propiedad tendrá aplicado el DebuggerHiddenAttribute.
  • El nombre del tipo se iniciará con "<>" y contienen "AnonymousType"

Muy poco de esto está garantizado por la especificación, sin embargo - por lo que podría cambiar en la próxima versión del compilador , o si usa Mono, etc.

+7

El <> prefijo de nombre es C# solamente. En VB, el prefijo del nombre será "VB $ AnonymousType" – JaredPar

+1

Ooh, vale la pena saberlo. Me atrevo a decir que algunas de las otras cosas solo se aplican a C# también, especialmente porque las de VB pueden ser mutables. Editará para reflejar eso. –

+0

Escaneé el resto de las entradas y solo hay otros dos errores de VB. Los campos no tienen el prefijo de nombre <> _. Además, la versión de VB tiene una propiedad privada adicional llamada AtDebuggerDisplay que se utiliza por motivos de rendimiento al depurar – JaredPar

4

Por lo que recuerdo, hay un marcador [CompilerGenerated] ... 2 segundos

Además, el nombre será extraño, y que será un tipo genérico ;-P

En realidad, para un "hacerse" etc. Probablemente usaría un método estático (sin extensión).

Si solo quiere una manera de obtener el valor de una instancia de un anon-type (en un momento posterior), una lambda es probablemente la mejor opción, tenga en cuenta que necesita algunos trucos para lograr esto:

static void Main() 
    { 
     var foo = new { name = "John", age = 25 }; 
     var func = Get(foo, x => x.age); 
     var bar = new { name = "Marc", age = 30 }; 
     int age = func(bar); 
    } 
    // template here is just for type inference... 
    static Func<TSource, TValue> Get<TSource, TValue>(
     TSource template, Func<TSource, TValue> lambda) 
    { 
     return lambda; 
    } 

(re editar el comentario) definitivamente es este atributo:

 var foo = new { A = "B" }; 
     Type type = foo.GetType(); 

     CompilerGeneratedAttribute attrib = (CompilerGeneratedAttribute) Attribute.GetCustomAttribute(
      type, typeof(CompilerGeneratedAttribute)); // non-null, therefore is compiler-generated 
+0

No, ningún atributo generado por el compilador – JaredPar

+0

@JaredPar: Ciertamente está en mi pequeña prueba. –

+1

[CompilerGenerated] designa un universo mucho más grande que los tipos anónimos. – JaredPar

1

a los efectos de los métodos de extensión que no hay manera de distinguir un tipo anónimo. Los métodos de extensión funcionan especificando un método para un tipo de nombre de tiempo de compilación. Los tipos anónimos no son identificables y, por lo tanto, no son visibles en el momento de la compilación. Esto los hace incompatibles con los métodos de extensión.

+0

Bueno, no se puede hacer una sobrecarga más específica para un tipo anónimo; sin embargo, los métodos de extensión son (en general) de alguna manera en su * la mayoría * útiles con tipos anónimos. –

+0

¿De qué manera? No hay forma de acceder de forma estática a un miembro de un tipo anónimo a través de un método de extensión genérico. Puede utilizar un hack glorioso en un método de extensión no genérico, pero implica crear un tipo no utilizado, lanzar y obtener el valor – JaredPar

+0

. En realidad, puede hacerlo a través de un lambda, etc. Pero un método de extensión genérico en (por ejemplo) IEnumerable etc. es el mecanismo principal para pasar un tipo de anon (T) fuertemente tipado de un método y trabajar con él de una manera útil (a través de Func , Acción , etc.). –

Cuestiones relacionadas