2010-09-23 4 views
55

Gibt es eine Weise, die ich wie so eine generierte Code-Datei haben:Kann ich Eigenschaften in Teilklassen definieren und sie dann mit Attributen in einer anderen Teilklasse markieren?

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

und dann in einer anderen Datei:

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

Damit ich eine Klasse aus der Datenbank generiert haben und dann verwenden eine nicht generierte Datei, um es zu markieren?

+0

Wie viel „aus der Datenbank generiert“ wird? Nur Property-Definitionen oder auch Code? – snemarch

+1

Kurze Antwort, nein. Lange Antwort, dup von http://stackoverflow.com/questions/456624/associate-attribute-with-code-generated-property-in-net. –

+0

@snemarch: nur Eigenschaftsdefinitionen, ich plane jeden anderen Code von Hand. –

Antwort

24

ich so etwas wie dies in einem Artikel von Scott Guthrie (nahe dem Ende davon) getan gesehen habe - versuchte es selbst nicht, though.
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

Diese Antwort muss erwähnt werden, ist aber keine allgemeine Lösung für die Frage des OP. Verbraucher der Attribute müssen immer noch wissen, nach der Metadatenklasse zu suchen - d.h. diese Attribute werden * nicht * von Attribute.GetCustomAttribute (...) zurückgegeben. (Zum Glück für viele Anwendungsfälle, die Verbraucher werden von MS geschrieben und in bestimmten Situationen wird dies funktionieren.) –

+0

Diese Lösung löst das Problem nicht. Warum suchen wir Mitglieder in einer anderen Datei zu dekorieren? Weil die Klasse jedes Mal, wenn der Designer ausgeführt wird, ÜBERSCHRITTEN ist. Daher wird Ihr Attribut '[MetaDataType ...' 'jedes Mal gelöscht, wenn der Designer –

+0

@Desolator ausführt. Die Idee ist, dass Sie das 'MetadataType'-Attribut nicht in die vom Designer erzeugte Datei einfügen, sondern in die andere Datei, in der die Teilklasse 'Person' definiert ist. –

0

Nicht als solche; Der Compiler wird sich beschweren, dass das Mitglied in mehreren Teilen definiert ist. Da die Verwendung von benutzerdefinierten Attributen jedoch reflektiv ist, könnten Sie eine "metadata" -Klasse definieren und diese zum Enthalten von Dekoratoren verwenden.

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

Wie oft ist es, dass der Akteur, der die Attribute zu seinen Eigenschaften hinzufügt, auch die Person ist, die sie verbraucht und deshalb wissen wird, zu suchen die magischen "Meta" -Klassen? –

+0

Ziemlich oft, nach meiner Erfahrung. Dies würde für ein vorhandenes, aspektorientiertes Framework nicht funktionieren, aber wenn Sie Ihre Domain beispielsweise mit benutzerdefinierten Validierungsattributen dekorieren, sind Sie derjenige, der nach ihnen sucht und wo definieren kann. Mein Team hat genau dies bei einem unserer Projekte getan. Der Hauptnachteil besteht darin, nicht nach der anderen Klasse zu suchen; Bei der Entwicklung werden zwei parallele Klassen beibehalten, eine funktionale, die andere dekorative. Auch in Teilklassen wäre das ein Problem, wenn Sie Teilfelder/Eigenschaften überhaupt erst definieren könnten. – KeithS

53

Ich weiß, dass dies eine alte Frage, aber hier ist die Lösung, die ich für solche Fälle verwendet haben. Dies ist nützlich, wenn Sie automatisch generierte Klassen haben, die Sie mit Attributen dekorieren möchten. Lassen Sie uns sagen, dass dies die automatisch generierte Klasse:

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

Und lassen Sie uns sagen, ich möchte ein Attribut hinzufügen, dass Benutzer-ID angeben, ist der Schlüssel. Ich würde dann eine partielle Klasse in einer anderen Datei wie folgt erstellen:

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

Arbeitete wie ein Charme! Vielen Dank!!! –

+0

Große Lösung. Ich wusste, dass Sie die partielle Klasse mit Attributen in mehreren Dateien dekorieren und sogar Schnittstellen und eine geerbte Klasse zu ihrer Deklaration hinzufügen können, aber ich habe die Verbindung zum Attribut "MetadataType" nicht hergestellt. Gut gemacht! – Pflugs

+0

Was ist, wenn ich dem Konstruktor von 'UserProfile' ein Attribut hinzufügen möchte? – Botis

1

Diese meine Dateien Antwort
andere Klasse ist oder Sie können die Metadaten in einer gleichen Datei kombinieren, aber der Namespace die same..so halten sie können sich offensichtlich sehen.

Denken Sie daran, wenn Sie Ihr Modell aktualisieren, wie zum Beispiel weitere Spalten hinzufügen, müssen Sie auch die Projektklasse aktualisieren.

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

Sie benötigen eine partielle Klasse für Ihre A Klasse zu definieren, wie unter Beispiel

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; } 
} 
Verwandte Themen