96 votes

Puis-je définir des propriétés dans des classes partielles, puis les marquer avec des attributs dans une autre classe partielle ?

Existe-t-il un moyen d'obtenir un fichier de code généré de la manière suivante ?

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

et ensuite dans un autre fichier :

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

Ainsi, je peux avoir une classe générée à partir de la base de données et ensuite utiliser un fichier non généré pour la baliser ?

0 votes

Que signifie "généré à partir de la base de données" ? Seulement les définitions de propriétés, ou aussi le code ?

1 votes

Réponse courte, non. Réponse longue : deux fois plus stackoverflow.com/questions/456624/ .

0 votes

@snemarch : définitions de propriétés uniquement, je prévois de faire tout autre code à la main.

96voto

Voici la solution que j'ai utilisée dans de tels cas. Elle est utile lorsque vous avez des classes générées automatiquement que vous voulez décorer avec des attributs. Disons que ceci est la classe auto-générée :

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

Et disons que je voudrais ajouter un attribut pour spécifier que UserId est la clé. Je créerais alors une classe partielle dans un autre fichier comme ceci :

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

1 votes

Excellente solution. Je savais que l'on pouvait décorer la classe partielle avec des attributs dans plusieurs fichiers et même ajouter des interfaces et une classe héritée à sa déclaration, mais je n'avais pas fait le lien avec le fichier MetadataType attribut. Bravo !

0 votes

Que faire si je veux ajouter un attribut au constructeur de UserProfile ?

0 votes

MetadataType ne peut être utilisé que pour les classes, que faire si je veux faire avec une structure ?

36voto

Dan Dumitru Points 3007

J'ai vu quelque chose comme ça dans un article de Scott Guthrie (vers la fin) - je n'ai pas essayé moi-même, cependant.
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; }
}

10 votes

Cette réponse mérite d'être mentionnée, mais elle ne constitue pas une solution générale à la question posée par le PO. Les consommateurs des attributs doivent toujours savoir qu'il faut rechercher la classe de métadonnées, c'est-à-dire que ces attributs seront pas être retourné par Attribute.GetCustomAttribute(...). (Heureusement, pour de nombreux cas d'utilisation, les consommateurs sont écrits par MS et dans certaines situations, cela fonctionnera).

1 votes

Cette solution ne résout PAS le problème. Pourquoi cherchons-nous à décorer les membres dans un autre fichier ? Parce que la classe est SUR-écrite à chaque fois que le concepteur s'exécute. Ainsi, votre attribut [MetaDataType ... sera effacée à chaque fois que le concepteur exécutera

2 votes

@Desolator - L'idée est que vous ne mettez pas la MetadataType dans le fichier généré par le concepteur, vous le placez dans l'autre fichier où la classe partielle Person est défini.

2voto

CyberNinja Points 465

Voici ma réponse
différents fichiers de classe ou vous pouvez combiner les métadonnées dans un même fichier mais en gardant le même espace de nom pour qu'ils puissent se voir évidemment.

gardez à l'esprit que lorsque vous mettez à jour votre modèle, par exemple en ajoutant des colonnes, vous devez également mettre à jour la classe du projet.

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

1voto

Masoud Darvishian Points 910

Vous devez définir une classe partielle pour votre A comme dans l'exemple ci-dessous

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

0voto

KeithS Points 36130

Pas en tant que tel ; le compilateur se plaindra que le membre est défini en plusieurs parties. Cependant, comme l'utilisation d'attributs personnalisés est de nature réflexive, vous pourriez définir une classe "métadonnées" et l'utiliser pour contenir des décorateurs.

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();

2 votes

Combien de fois l'acteur qui ajoute les attributs à ses propriétés est aussi celui qui les consomme et saura donc chercher les classes magiques "Meta" ?

0 votes

Assez souvent, d'après mon expérience. Cela ne fonctionnerait pas pour un cadre orienté aspect existant, mais si vous décorez votre domaine avec, disons, des attributs de validation personnalisés, c'est vous qui les recherchez et vous pouvez définir où. Mon équipe a fait exactement cela sur l'un de nos projets. Le principal inconvénient n'est pas de chercher l'autre classe ; c'est de maintenir deux classes parallèles pendant le développement, l'une fonctionnelle, l'autre décorative. Ce serait également un problème dans les classes partielles, si vous étiez en mesure de définir des champs/propriétés partiels en premier lieu.

0 votes

KirkWoll C'est une bonne question. Je pense que c'est un bon argument pour mettre les méta classes dans le même fichier que la classe annotée, potentiellement même en haut du fichier, de sorte que les autres codeurs seront plus susceptibles de trouver ce code.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X