web-dev-qa-db-fra.com

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 de créer un fichier de code tel que:

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

puis dans un autre fichier:

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

Pour que je puisse avoir une classe générée à partir de la base de données puis utiliser un fichier non généré pour la marquer?

62
Chris McCall

J'ai vu quelque chose de semblable dans un article de Scott Guthrie (vers la fin) - je ne l'ai pas essayé moi-même.
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; }
}
29
Dan Dumitru

Voici la solution que j'ai utilisée pour de tels cas. Cela est utile lorsque vous avez des classes générées automatiquement que vous souhaitez décorer avec des attributs. Disons que c'est la classe générée automatiquement:

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 ensuite une classe partielle dans un autre fichier comme celui-ci:

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

C'est ma réponse
Différents fichiers de classe ou vous pouvez combiner les métadonnées dans un même fichier tout en conservant l’espace de nom identique .. afin qu’ils puissent se voir de manière évidente.

gardez à l'esprit que lorsque vous mettez à jour votre modèle, comme ajouter des colonnes supplémentaires, vous devez également mettre à jour la classe de 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
{
}
2
CyberNinja

Vous devez définir une classe partielle pour votre classe 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; }
}
1

Pas comme tel; le compilateur se plaint que le membre est défini en plusieurs parties. Cependant, comme l'utilisation d'attributs personnalisés est de nature réflexive, vous pouvez 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();
0
KeithS