Associate attribute with generated property code in .net

I want to set the attribute for an open property in .NET, however I do not have access to the explicit property itself, since it was code generated in another file.

I have this field:

public virtual string Name { get; set; } 

I want to install this:

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

My class is marked as partial, but you cannot have partial properties. I thought I was doing something with the MetadataType class, which is a new feature of Dynamic Data and DataAnnotations, but alas, I feel that it can only be used with dynamic data, is that true?

Citation: 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

Is it possible to set these attributes (even via web.config!) Without touching the code generated by the class?

Thanks in advance, Graham

+16
code-generation attributes
Jan 19 '09 at 5:36
source share
4 answers

This is a known nuisance; you simply cannot add metadata to generated members.

There are 6 options (in increasing order of effort):

  • if you have an attribute, give it the opportunity to declare it against the class, for example: [ValidateNonEmpty("Name", "Name is required", ExecutionOrder = 1)] - then add some attributes to the definition of the partial class
  • use virtual / interface / etc method to request this, not through attributes
  • sublimate the generated type; override or re-declare member by adding metadata (really dirty)
  • use a custom TypeDescriptionProvider to provide dynamic metadata (lots and lots of work) - provided that the consumer respects TypeDescriptor ; most affectionate consumers, but, for example, Expression (used by many LINQ providers) is not
  • change the code generator / write your own
  • try to do something like PostSharp to do the job (I have not found a way to do this, but I am very happy to hear if you find a way!)

Usually I have success with the first parameter, unless it is a system attribute ( [DisplayName] , etc.). If [ValidateNonEmpty] is determined by dynamic data, you may not be able to do this.

+22
Jan 19 '09 at 5:54
source share

Since the generated class is a partial class, the following should work:

  • Create an interface in which this property is declared and decorate it with the ValidateNonEmpty attribute.
  • Create your own incomplete class with the same name as the AutoGenerated class, and create this interface that you just created.
  • Now the property should be decorated with this attribute

For example:

 // 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; } } 

I got this idea from geekswithblogs .

+6
Oct 16 '13 at 10:04 on
source share

This is a great solution, but it did not work for my problem. I am using EF 6 with code-generated classes from an existing database. One of the columns in the table is IDENTITY with automatically generated values. However, the generated incomplete class did not provide the [DatabaseGenerated (DatabaseGeneratedOption.Identity)] attribute needed to generate the database. The result is the error: "Cannot insert explicit value for the identity column into the table" mytable "if the IDENTITY_INSERT parameter is set to OFF." I tried your solution, but it didn’t work. But if I add an attribute to the original generated class, it works. Therefore, I am still trying to find a solution that does not require changing the automatically generated file.

Here is the code I tried using your solution:

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

source:

 [Table("MyTable")] public partial class MyTable { [Key] [Column(Order = 1)] public int ID { get; set; } } 
+2
May 7 '14 at 16:24
source share

Another option is to wrap properties inside non-degenerate properties in the same class. Not ideal, because you can have dual properties, but if you can make your generator secure with properties, that would be a pretty good approach.

It was just necessary to solve this problem: Entity Framework generates classes, I want to serialize them in JSON with simpler names.

 // 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; } } 

and add-in class:

 [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; } } } 
+1
Nov 15 '12 at 4:14
source share



All Articles