.net attributes code-generation

Atributo asociado con la propiedad de código generado en.net



attributes code-generation (4)

Esta es una molestia conocida; simplemente no puede agregar metadatos a los miembros generados.

Aquí hay 6 opciones (en orden creciente de esfuerzo):

  • si posee el atributo, haga que sea posible declararlo en contra de la clase, por ejemplo: [ValidateNonEmpty("Name", "Name is required", ExecutionOrder = 1)] - luego agregue múltiples atributos a la definición de clase parcial
  • utilice un método virtual / interfaz / etc para consultar esto, en lugar de a través de atributos
  • subclase el tipo generado; anula o vuelve a declarar al miembro, agregando los metadatos (realmente desordenado)
  • utilice un TypeDescriptionProvider personalizado para proporcionar metadatos dinámicos (mucho trabajo), suponiendo que el consumidor respeta TypeDescriptor ; la mayoría de los consumidores relacionados con la vinculación lo hacen, pero, por ejemplo, Expression (utilizado por muchos proveedores de LINQ) no lo hace
  • cambie el generador de código / escriba su propio
  • intenta extender algo como PostSharp para hacer el trabajo (no he encontrado la manera de hacerlo, pero me encantaría saber si encuentras una forma).

Normalmente tengo éxito con la primera opción, a menos que sea un atributo definido por el sistema ( [DisplayName] , etc.). Si [ValidateNonEmpty] está definido por datos dinámicos, es posible que no pueda hacer esto.

Deseo establecer un atributo en una propiedad pública en .NET, sin embargo, no tengo acceso a la propiedad explícita en sí misma, ya que este ha sido generado en otro archivo.

Tengo este campo:

public virtual string Name { get; set; }

Deseo establecer esto:

[ValidateNonEmpty("Name is required", ExecutionOrder = 1)] public virtual string Name { get; set; }

Mi clase está marcada como parcial, pero no puede tener propiedades parciales. Pensé que estaba trabajando en algo con la clase MetadataType, que es una nueva característica de Dynamic Data y DataAnnotations, pero lamentablemente creo que solo se puede usar con Dynamic Data, ¿es así?

Citaciones: http://blogs.oosterkamp.nl/blogs/jowen/archive/2008/10/16/metadatatype-attribute.aspx http://blogs.msdn.com/davidebb/archive/2008/06/16/dynamic -data-and-the-associated-metadata-class.aspx

¿Hay alguna forma en que pueda establecer estos atributos (incluso a través de web.config) sin tocar la clase generada por el código?

Gracias de antemano, Graham


Otra opción es ajustar las propiedades dentro de las propiedades no generadas en la misma clase. No es ideal porque puede terminar teniendo propiedades dobles, pero si puede hacer que su generador haga propiedades protegidas sería un enfoque bastante bueno.

Solo tuve que lidiar con este problema: Entity Framework genera clases, quiero serializarlas en JSON con nombres más simples.

// GENERATED BY EF public partial class ti_Users { public ti_Users() { this.ti_CardData = new HashSet<ti_CardData>(); this.ti_Orders = new HashSet<ti_Orders>(); } protected int userId { get; set; } protected string userName { get; set; } protected string userEmail { get; set; } protected string userPassHash { get; set; } protected Nullable<System.DateTime> userLastLogin { get; set; } protected string userLastIP { get; set; } public virtual ICollection<ti_CardData> ti_CardData { get; set; } public virtual ICollection<ti_Orders> ti_Orders { get; set; } }

y la clase adicional:

[JsonObject(memberSerialization: MemberSerialization.OptIn)] public partial class ti_Users { [JsonProperty] public int UserId { get { return this.userId; } set { this.userId = value; } } [JsonProperty] public string Name { get { return this.userName; } set { this.userName = value; } } [JsonProperty] public string Email { get { return this.userEmail; } set { this.userEmail = value; } } [JsonProperty] public string PassHash { get { return this.userPassHash; } set { this.userPassHash = value; } } }


Como la clase generada es una clase parcial, lo siguiente debería funcionar:

  1. Cree una interfaz que tenga esta propiedad declarada en ella y decore con el atributo ValidateNonEmpty.
  2. Cree su propia clase parcial con el mismo nombre que la clase AutoGenerated, y haga que implemente la interfaz que acaba de crear.
  3. La propiedad ahora debería estar decorada con ese atributo

Por ejemplo:

// Decorate the properties with attributes as required public interface IMyInterface { [ValidateNonEmpty("Name is required")] string Name { get; set; } } // This is the partial class I created, that implements the interface public partial class MyGeneratedClass : IMyInterface { } // This is the auto-generated class public partial class MyGeneratedClass { public virtual string Name { get; set; } }

Tengo esta idea de geekswithblogs .


Esta es una gran solución, pero no funcionó para mi problema. Estoy usando EF 6 con clases generadas por código primero de una base de datos existente. Una de las columnas de una tabla es una IDENTIDAD con valores generados automáticamente. Sin embargo, la clase parcial generada no proporcionó el atributo [DatabaseGenerated (DatabaseGeneratedOption.Identity)] necesario para que la base de datos genere la clave. El resultado es el error " No se puede insertar el valor explícito para la columna de identidad en la tabla ''mitabla'' cuando IDENTITY_INSERT está establecido en OFF. ". Probé tu solución pero no funcionó. Pero si agrego el atributo a la clase generada original, funciona. Por lo tanto, sigo intentando encontrar una solución que no requiera la modificación del archivo generado automáticamente.

Aquí está el código que traté de usar su solución:

public interface IMyTable { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] int ID { get; set; } } public partial class MyTable : IMyTable { }

código original generado:

[Table("MyTable")] public partial class MyTable { [Key] [Column(Order = 1)] public int ID { get; set; } }