2009-10-18 17 views
11

Necesito recuperar todas las propiedades de un tipo anónimo que se pueden escribir.Obtener propiedades de lectura/escritura de tipo anónimo

por ejemplo:

var person = new {Name = "Person's Name", Age = 25}; 
Type anonymousType = person.GetType(); 
var properties = anonymousType.GetProperties(BindingFlags.Public | BindingFlags.Instance); 

El problema es que todas las propiedades tienen su propiedad CanWritefalse. Esto se devuelve como verdadero para los tipos no anónimos.
También he intentado hacer una llamada a PropertyInfo.GetSetMethod() que devuelve null.
¿Cómo puedo verificar si la propiedad se puede escribir?

Editar: Quizás sea suficiente saber si un tipo es anónimo o no. ¿Cómo puedo averiguar si un tipo es anónimo usando la reflexión?

Respuesta

18

Los tipos anónimos generados a partir de C# son siempre inmutables, por lo que el conjunto de propiedades modificables está vacío. En VB es opcional: cada propiedad tiene como valor predeterminado ser mutable, pero si la antepone con Key es inmutable; solo las propiedades declaradas usando Key cuentan para igualdad y generación de código hash. Personalmente prefiero el enfoque de C#.

CanWrite no es always devuelto como verdadero para las propiedades en tipos no anónimos, solo para las que se pueden escribir. Las propiedades pueden ser de solo lectura, solo escritura o lectura y escritura. Por ejemplo:

public class Test 
{ 
    // CanWrite will return false. CanRead will return true. 
    public int ReadOnly { get { return 10; } } 

    // CanWrite will return true. CanRead will return false. 
    public int WriteOnly { set {} } 

    // CanWrite will return true. CanRead will return true. 
    public int ReadWrite { get { return 10; } set {} } 
} 
+0

Hola, "is not always"? Podrías profundizar en eso un poco. También esperaba que se generara un método de configuración. ¿Es el compilador lo suficientemente inteligente como para generar un setter solo si se usa? - Gracias. –

+0

¿También es posible saber si un tipo es anónimo usando la reflexión? –

+0

Usted * no puede * usar un setter con un tipo anónimo generado por C# - como digo, siempre es inmutable. Para los tipos con nombre, tener o no un setter dependerá de la declaración, como se muestra en el ejemplo. En cuanto a detectar si un tipo fue creado por el compilador, hay otra pregunta SO sobre eso en alguna parte. Trataré de encontrarlo. –

1

No se pueden asignar las propiedades de los tipos anónimos, por lo que los informes de reflexión son correctos.

Si observara el IL compilado, notará que aunque el código C# parece que está usando un inicializador normal, el compilador lo reescribe para que sea una llamada de constructor, lo que permite que las propiedades sean no escribible fuera de la clase.

1

¿Cómo puedo saber si un tipo es anónimo mediante la reflexión?

Creo que se puede comprobar si el tipo tiene el atributo CompilerGenerated

2

No hay manera confiable para determinar si un tipo es anónimo como el tiempo de ejecución .NET 2.0 no era compatible con los tipos anónimos. Confiar en el formato del "nombre generado por el compilador" no es una solución segura ya que es probable que esto cambie con las diferentes versiones del compilador.

Parece que respondió su propia pregunta con respecto a "Cómo puedo verificar si la propiedad se puede escribir en" con las afirmaciones anteriores: CanWrite es falso y GetSetMethod (verdadero) devuelve nulo. Esos son dos signos de que no puedes escribir en la propiedad.

Como estamos en el tiempo de ejecución de .NET 2.0, no hay una propiedad "IsAnonymous" en System.Type, por lo que realmente no tiene ningún método confiable para identificar un tipo anónimo.

0

¿Cómo puedo saber si un tipo es anónimo mediante la reflexión?

Simplemente use este código.

var isAnonymousType = Attribute.IsDefined(dataType, typeof (CompilerGeneratedAttribute), false) && dataType.IsGenericType && dataType.FullName.Contains("Anonymous") && (dataType.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic; 
+0

Esta [respuesta] (http://stackoverflow.com/a/16349607/945456) sugiere que simplemente puede verificar el 'CompilerGeneratedAttribute'. ¿Son todos estos otros controles realmente necesarios? Editar: parece que obtuvo información de la misma fuente que esta [respuesta] (http://stackoverflow.com/a/2483054/945456)? –

Cuestiones relacionadas