Quelqu'un peut-il m'expliquer un exemple très basique d'un attribut personnalisé avec du code ?
Réponses
Trop de publicités?Vous commencez par écrire une classe qui dérive de Attribut :
public class MyCustomAttribute: Attribute
{
public string SomeProperty { get; set; }
}
Vous pouvez alors décorer n'importe quoi (classe, méthode, propriété, ...) avec cet attribut :
[MyCustomAttribute(SomeProperty = "foo bar")]
public class Foo
{
}
et enfin vous utiliserez la réflexion pour le récupérer :
var customAttributes = (MyCustomAttribute[])typeof(Foo).GetCustomAttributes(typeof(MyCustomAttribute), true);
if (customAttributes.Length > 0)
{
var myAttribute = customAttributes[0];
string value = myAttribute.SomeProperty;
// TODO: Do something with the value
}
Vous pouvez limiter les types de cible auxquels cet attribut personnalisé peut être appliqué à l'aide de l'attribut AttributUsage attribut :
/// <summary>
/// This attribute can only be applied to classes
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class MyCustomAttribute : Attribute
Des choses importantes à savoir sur les attributs :
- Les attributs sont des métadonnées.
- Ils sont intégrés dans l'assemblage à temps de compilation ce qui a des implications très sérieuses sur la façon dont vous pourriez définir leurs propriétés. Seules les valeurs constantes (connues au moment de la compilation) sont acceptées.
- La seule façon de donner du sens et d'utiliser des attributs personnalisés est d'utiliser Réflexion . Donc si vous n'utilisez pas la réflexion au moment de l'exécution pour les récupérer et décorer quelque chose avec un attribut personnalisé, ne vous attendez pas à ce qu'il se passe grand chose.
- Le moment de la création des attributs est non déterministe. Ils sont instanciés par le CLR et vous n'avez absolument aucun contrôle là-dessus.
Alors que le code pour créer un Attribut est assez simple, il est très important que vous compreniez ce que sont les attributs :
Les attributs sont des métadonnées compilées dans votre programme. Les attributs eux-mêmes n'ajoutent aucune fonctionnalité à une classe, une propriété ou un module - ce sont simplement des données. Toutefois, en utilisant la réflexion, il est possible de tirer parti de ces attributs afin de créer des fonctionnalités.
Donc, par exemple, regardons l' Bloc d'application de validation de Microsoft. Bibliothèque d'entreprise . Si vous regardez un exemple de code, vous verrez :
/// <summary>
/// blah blah code.
/// </summary>
[DataMember]
[StringLengthValidator(8, RangeBoundaryType.Inclusive, 8, RangeBoundaryType.Inclusive, MessageTemplate = "\"{1}\" must always have \"{4}\" characters.")]
public string Code { get; set; }
D'après l'extrait ci-dessus, on pourrait supposer que le code sera toujours validé, chaque fois qu'il sera modifié, conformément aux règles du validateur (dans l'exemple, avoir au moins 8 caractères et au plus 8 caractères). Mais la vérité est que l'Attribut ne fait rien ; comme mentionné précédemment, il ne fait qu'ajouter des métadonnées à la propriété.
Cependant, la bibliothèque d'entreprise a Validation.Validate
qui examinera votre objet, et pour chaque propriété, il vérifiera si le contenu viole la règle indiquée par l'attribut.
C'est ainsi que vous devez considérer les attributs : un moyen d'ajouter des données à votre code qui peuvent être utilisées ultérieurement par d'autres méthodes/classes/etc.
Utilisation/Copiage La grande réponse de Darin Dimitrov Si vous voulez accéder à un attribut personnalisé sur une propriété et non sur une classe, voici comment faire :
La propriété décorée [de la classe Foo
] :
[MyCustomAttribute(SomeProperty = "This is a custom property")]
public string MyProperty { get; set; }
Je vais le chercher :
PropertyInfo propertyInfo = typeof(Foo).GetProperty(propertyToCheck);
object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true);
if (attribute.Length > 0)
{
MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0];
string propertyValue = myAttribute.SomeProperty;
}
Vous pouvez l'inclure dans une boucle et utiliser la réflexion pour accéder à cet attribut personnalisé sur chaque propriété de la classe Foo
également :
foreach (PropertyInfo propertyInfo in Foo.GetType().GetProperties())
{
string propertyName = propertyInfo.Name;
object[] attribute = propertyInfo.GetCustomAttributes(typeof(MyCustomAttribute), true);
// Just in case you have a property without this annotation
if (attribute.Length > 0)
{
MyCustomAttribute myAttribute = (MyCustomAttribute)attribute[0];
string propertyValue = myAttribute.SomeProperty;
// TODO: whatever you need with this propertyValue
}
}
Un grand merci à toi, Darin !
La réponse courte est que pour créer un attribut en c#, il suffit d'hériter de la classe Attribute, juste ceci :)
Mais ici, je vais expliquer les attributs en détail :
En principe, les attributs sont des classes que nous pouvons utiliser pour appliquer notre logique aux assemblages, classes, méthodes, propriétés, champs, ...
En .Net, Microsoft a fourni certains attributs prédéfinis comme les attributs obsolètes ou de validation comme ([Required], [StringLength(100)], [Range(0, 999.99)]), nous avons également des attributs comme les ActionFilters en asp.net qui peuvent être très utiles pour appliquer notre logique souhaitée à nos codes (lire este un article sur les filtres d'action si vous êtes passionné pour l'apprendre)
d'autre part, vous pouvez appliquer une sorte de configuration sur votre attribut via AttibuteUsage.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]
Lorsque vous décorez une classe d'attributs avec AttributeUsage, vous pouvez indiquer au compilateur C# où je vais utiliser cet attribut : Je vais l'utiliser sur les classes, sur les assemblages, sur les propriétés ou sur ... et mon attribut est autorisé à être utilisé plusieurs fois sur des cibles définies (classes, assemblages, propriétés, ...) ou non !
Après cette définition des attributs, je vais vous montrer un exemple : Imaginons que nous voulions définir une nouvelle leçon à l'université et que nous voulions autoriser uniquement les administrateurs et les maîtres de notre université à définir une nouvelle leçon, ok ?
namespace ConsoleApp1
{
/// <summary>
/// All Roles in our scenario
/// </summary>
public enum UniversityRoles
{
Admin,
Master,
Employee,
Student
}
/// <summary>
/// This attribute will check the Max Length of Properties/fields
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]
public class ValidRoleForAccess : Attribute
{
public ValidRoleForAccess(UniversityRoles role)
{
Role = role;
}
public UniversityRoles Role { get; private set; }
}
/// <summary>
/// we suppose that just admins and masters can define new Lesson
/// </summary>
[ValidRoleForAccess(UniversityRoles.Admin)]
[ValidRoleForAccess(UniversityRoles.Master)]
public class Lesson
{
public Lesson(int id, string name, DateTime startTime, User owner)
{
var lessType = typeof(Lesson);
var validRolesForAccesses = lessType.GetCustomAttributes<ValidRoleForAccess>();
if (validRolesForAccesses.All(x => x.Role.ToString() != owner.GetType().Name))
{
throw new Exception("You are not Allowed to define a new lesson");
}
Id = id;
Name = name;
StartTime = startTime;
Owner = owner;
}
public int Id { get; private set; }
public string Name { get; private set; }
public DateTime StartTime { get; private set; }
/// <summary>
/// Owner is some one who define the lesson in university website
/// </summary>
public User Owner { get; private set; }
}
public abstract class User
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class Master : User
{
public DateTime HireDate { get; set; }
public Decimal Salary { get; set; }
public string Department { get; set; }
}
public class Student : User
{
public float GPA { get; set; }
}
class Program
{
static void Main(string[] args)
{
#region exampl1
var master = new Master()
{
Name = "Hamid Hasani",
Id = 1,
DateOfBirth = new DateTime(1994, 8, 15),
Department = "Computer Engineering",
HireDate = new DateTime(2018, 1, 1),
Salary = 10000
};
var math = new Lesson(1, "Math", DateTime.Today, master);
#endregion
#region exampl2
var student = new Student()
{
Name = "Hamid Hasani",
Id = 1,
DateOfBirth = new DateTime(1994, 8, 15),
GPA = 16
};
var literature = new Lesson(2, "literature", DateTime.Now.AddDays(7), student);
#endregion
ReadLine();
}
}
}
Dans le monde réel de la programmation, nous n'utilisons peut-être pas cette approche pour l'utilisation des attributs et je l'ai dit en raison de son intérêt pédagogique pour l'utilisation des attributs.