2010-09-23 13 views
55

¿Hay alguna manera de tener un archivo de código generado de esta manera:¿Puedo definir propiedades en clases parciales, y luego marcarlas con atributos en otra clase parcial?

public partial class A { 
public string a {get; set;} 
} 

y luego en otro archivo:

public partial class A { 
[Attribute("etc")] 
public string a {get; set;} 
} 

De modo que pueda tener una clase generada a partir de la base de datos y luego utilizar un archivo no generado para marcarlo?

+0

¿Cuánto es "generada a partir de la base de datos"? ¿Solo las definiciones de propiedad, o el código también? – snemarch

+1

Respuesta corta, no. Respuesta larga, dup de http://stackoverflow.com/questions/456624/associate-attribute-with-code-generated-property-in-net. –

+0

@snemarch: solo definiciones de propiedad, planeo hacer cualquier otro código a mano. –

Respuesta

24

que he visto algo como esto en un artículo hecho por Scott Guthrie (cerca del final de la misma) - no lo probé a mí mismo, sin embargo.
http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx

[MetadataType(typeof(Person_Validation))] 
public partial class Person 
{ 
    // Partial class compiled with code produced by VS designer 
} 

[Bind(Exclude="ID")] 
public class Person_Validation 
{ 
    [Required(ErrorMessage = "First Name Required")] 
    [StringLength(50, ErrorMessage = "Must be under 50 characters")] 
    public string FirstName { get; set; } 

    [Required(ErrorMessage = "Last Name Required")] 
    [StringLength(50, ErrorMessage = "Must be under 50 characters")] 
    public string LastName { get; set; } 

    [Required(ErrorMessage = "Age Required")] 
    [Range(0, 120, ErrorMessage = "Age must be between 0 and 120")] 
    public int Age { get; set; } 

    [Required(ErrorMessage = "Email Required")] 
    [Email(ErrorMessage = "Not a valid email")] 
    public string Email { get; set; } 
} 
+5

Esta respuesta merece ser mencionada, pero no es una solución general a la pregunta planteada por el OP. Los consumidores de los atributos aún necesitan saber para buscar la clase de metadatos, es decir, estos atributos * no * serán devueltos por Attribute.GetCustomAttribute (...). (Afortunadamente para muchos casos de uso, los consumidores están escritos por MS y en ciertas situaciones esto funcionará.) –

+0

Esta solución NO resuelve el problema. ¿Por qué buscamos decorar miembros en otro archivo? Porque la clase se OVERWRITTEN cada vez que se ejecuta el diseñador. Por lo tanto, su atributo '[MetaDataType ...' se borrará cada vez que el diseñador ejecute –

+0

@Desolator - La idea es que no coloque el atributo 'MetadataType' en el archivo generado por el diseñador, sino que lo ponga en el otro archivo donde se define la clase parcial 'Persona'. –

0

No como tal; el compilador se quejará de que el miembro está definido en varias partes. Sin embargo, como el uso de atributos personalizados es de naturaleza reflexiva, puede definir una clase de "metadatos" y usarla para contener decoradores.

public class A 
{ 
    public string MyString; 
} 

public class AMeta 
{ 
    [TheAttribute("etc")] 
    public object MyString; 
} 

... 

var myA = new A(); 
var metaType = Type.GetType(myA.GetType().Name + "Meta"); 
var attributesOfMyString = metaType.GetMember("MyString").GetCustomAttributes(); 
+1

¿Con qué frecuencia el actor que agrega los atributos a sus propiedades es también la persona que los consume y por lo tanto sabrá buscar las clases mágicas de "Meta" –

+0

Muy a menudo, en mi experiencia. Esto no funcionaría para un marco existente orientado a aspectos, pero si estuviera decorando su dominio con, por ejemplo, atributos de validación personalizados, usted es el que los busca y puede definir dónde. Mi equipo ha hecho exactamente esto en uno de nuestros proyectos. La principal desventaja es no buscar la otra clase; mantiene dos clases paralelas durante el desarrollo, una funcional y la otra decorativa. Eso también sería un problema en las clases parciales, si pudieras definir campos/propiedades parciales en primer lugar. – KeithS

53

Sé que esto es una vieja pregunta, pero aquí es la solución que he estado utilizando para tales casos. Es útil cuando tiene clases generadas automáticamente que desea decorar con atributos. Digamos que esta es la clase generada automáticamente:

public partial class UserProfile 
{ 
    public int UserId { get; set; } 
    public string UserName { get; set; } 
    public string Firstname { get; set; } 
    public string Lastname { get; set; } 
} 

Y digamos, me gustaría añadir un atributo para especificar que UserId es la clave. Me gustaría a continuación, crear una clase parcial en otro archivo de la siguiente manera:

[Table("UserProfile")] 
[MetadataType(typeof(UserProfileMetadata))] 
public partial class UserProfile 
{ 
    internal sealed class UserProfileMetadata 
    { 
     [Key] 
     [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
     public int UserId { get; set; } 
    } 
} 
+1

¡Funcionó como un amuleto! ¡¡¡Gracias!!! –

+0

Gran solución. Sabía que se podía decorar la clase parcial con atributos en múltiples archivos e incluso agregar interfaces y una clase heredada a su declaración, pero no hice la conexión al atributo 'MetadataType'. ¡Bien hecho! – Pflugs

+0

¿Qué sucede si quiero agregar un atributo al constructor de 'UserProfile'? – Botis

1

Ésta es mi respuesta
archivos de clases diferentes o se pueden combinar los metadatos en un mismo archivo, pero mantener el espacio de nombres del same..so que pueden nos vemos obviamente.

tenga en cuenta que al actualizar su modelo, como agregar más columnas, también debe actualizar la clase de proyecto.

--your model class 
public partial class A { 
    public string a {get; set;} 
} 

--your project class 
public class Ametadata { 
    [Attribute("etc")] 
    public string a {get; set;} 
} 


[MetadataType(typeof(Ametadata))] 
public partial class A 
{ 
} 
0

Es necesario definir una clase parcial para su clase A al igual que a continuación ejemplo

using System.ComponentModel.DataAnnotations; 

// your auto-generated partial class 
public partial class A 
{ 
    public string MyProp { get; set; } 
} 

[MetadataType(typeof(AMetaData))] 
public partial class A 
{ 

} 

public class AMetaData 
{ 
    [System.ComponentModel.DefaultValue(0)] 
    public string MyProp { get; set; } 
} 
Cuestiones relacionadas