Ho provato molte volte ma ancora non sono in grado di capire l'utilizzo degli attributi personalizzati (ho già passato molti collegamenti).
Qualcuno può spiegarmi un esempio molto semplice di un attributo personalizzato con codice?
Ho provato molte volte ma ancora non sono in grado di capire l'utilizzo degli attributi personalizzati (ho già passato molti collegamenti).
Qualcuno può spiegarmi un esempio molto semplice di un attributo personalizzato con codice?
Risposte:
Sebbene il codice per creare un attributo personalizzato sia abbastanza semplice, è molto importante capire quali sono gli attributi:
Gli attributi sono metadati compilati nel tuo programma. Gli attributi stessi non aggiungono alcuna funzionalità a una classe, proprietà o modulo, ma solo dati. Tuttavia, utilizzando la riflessione, è possibile sfruttare questi attributi per creare funzionalità.
Quindi, ad esempio, diamo un'occhiata al Validation Application Block , dalla Enterprise Library di Microsoft . Se guardi un esempio di codice, vedrai:
/// <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; }
Dallo snippet sopra, si potrebbe intuire che il codice sarà sempre validato, ogni volta che viene modificato, secondo le regole del Validator (nell'esempio, avere almeno 8 caratteri e al massimo 8 caratteri). Ma la verità è che l'attributo non fa nulla; come accennato in precedenza, aggiunge solo metadati alla proprietà.
Tuttavia, Enterprise Library ha un Validation.Validate
metodo che esaminerà il tuo oggetto e, per ogni proprietà, controllerà se il contenuto viola la regola informata dall'attributo.
Quindi, è così che dovresti pensare agli attributi: un modo per aggiungere dati al tuo codice che potrebbero essere successivamente utilizzati da altri metodi / classi / ecc.
Inizi scrivendo una classe che deriva da Attribute :
public class MyCustomAttribute: Attribute
{
public string SomeProperty { get; set; }
}
Quindi potresti decorare qualsiasi cosa (classe, metodo, proprietà, ...) con questo attributo:
[MyCustomAttribute(SomeProperty = "foo bar")]
public class Foo
{
}
e infine useresti la riflessione per recuperarlo:
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
}
È possibile limitare i tipi di destinazione a cui applicare questo attributo personalizzato utilizzando l' attributo AttributeUsage:
/// <summary>
/// This attribute can only be applied to classes
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class MyCustomAttribute : Attribute
Cose importanti da sapere sugli attributi:
var value = typeof(Foo).GetCustomAttributes<MyCustomAttribute>().First().SomeProperty;
Utilizzo / copia della grande risposta di Darin Dimitrov , ecco come accedere a un attributo personalizzato su una proprietà e non su una classe:
La proprietà decorata [di classe Foo
]:
[MyCustomAttribute(SomeProperty = "This is a custom property")]
public string MyProperty { get; set; }
Recuperarlo:
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;
}
Puoi lanciarlo in un ciclo e utilizzare la riflessione per accedere a questo attributo personalizzato anche su ogni proprietà della classe Foo
:
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
}
}
Grazie mille a te, Darin !!
object[] attribute = propertyInfo.GetCustomAttributes(typeof(???), true);
Voglio solo iterare su tutti loro e chiamare un metodo m1()
di ogni attributo sconosciuto
La risposta breve è per creare un attributo in c # devi solo ereditarlo dalla classe Attribute, solo questo :)
Ma qui spiegherò in dettaglio gli attributi:
fondamentalmente gli attributi sono classi che possiamo usarli per applicare la nostra logica ad assembly, classi, metodi, proprietà, campi, ...
In .Net, Microsoft ha fornito alcuni attributi predefiniti come Obsolete o Attributi di convalida come ([Required], [StringLength (100)], [Range (0, 999.99)]), inoltre abbiamo tipi di attributi come ActionFilters in asp.net che può essere molto utile per applicare la nostra logica desiderata ai nostri codici (leggi questo articolo sui filtri di azione se sei appassionato di impararlo)
un altro punto, puoi applicare una sorta di configurazione al tuo attributo tramite AttibuteUsage.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]
Quando decori una classe di attributi con AttributeUsage puoi dire al compilatore c # dove userò questo attributo: lo userò sulle classi, sugli assembly sulle proprietà o su ... e il mio attributo può essere usato più volte su target definiti (classi, assembly, proprietà, ...) o no ?!
Dopo questa definizione degli attributi ti mostrerò un esempio: immagina di voler definire una nuova lezione all'università e di voler consentire solo ad amministratori e master della nostra università di definire una nuova lezione, 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();
}
}
}
Nel mondo reale della programmazione forse non usiamo questo approccio per usare gli attributi e l'ho detto a causa del suo punto educativo nell'uso degli attributi