//Attributes can be added to properties or classes depending on the attribute.
//They can also be used to keep a sort of static variable hidden to the object on classes, properties, fields, enums, Assemblys, methods, and other objects at verying scopes that can be revied later for different uses
//For example they can mark classes for behaviour or for checks
[Serializable] //<-A class marking attribute marking the your class to do the work of getting ready your class for serlization so you dont have to.
public class SomeAPIClass
{
//The attribute is always placed above the thing you wish to mark and can , seperated in the [ brackets or stacked in many [ brackets.
[APIAlwaysRequired(nameof(UserName))]//Property marking attributes
public string SomeValue { get; set; }
}
//To make a custom attribute class you can look into extending the attribute calls and marking it with attribute for the given object you want to mark
//Here is an example of a attribute to mark properies for a type of check
[System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.Field, Inherited = true)]
public class APIAlwaysRequiredAttribute : System.Attribute
{
public string ErrorMessage { get; set; } = "Your request is missing or with out a param.";
public APIAlwaysRequiredAttribute(){}
public APIAlwaysRequiredAttribute(string ParamName)
{
this.ErrorMessage = $"Your request is missing or with out the {ParamName} param."; ;
}
}
//You then will need to make use of your attribute in some way. Probably through reflection.
//Here is an example of the above attribute in use with a templatable generic check that saves you from writing too many vers your self. Let reflection and attributes take on all the work.
private static List<string> CheckObjectForErrors<T>(T obj, bool SkipPostErrors)
{
List<string> Errors = new List<string>();
Type ObjType = typeof(T);
PropertyInfo[] Properties = ObjType.GetProperties();
foreach (PropertyInfo P in Properties)
{
if (Attribute.IsDefined(P, typeof(APIAlwaysRequiredAttribute)))
{
if (P.GetValue(obj) == null)
{
APIAlwaysRequiredAttribute ErrorAttribute = (APIAlwaysRequiredAttribute)Attribute.GetCustomAttribute(P, typeof(APIAlwaysRequiredAttribute));
Errors.Add(ErrorAttribute.ErrorMessage);
}
}
}
if (Errors.Count() != 0)
return Errors;
return null;
}
//There are an an insane amount of ways you can use this like a Regex check that takes the Regex String in a var could be added
public static dynamic GetAttribute(Type objectType, string propertyName, Type attrType)
{
//get the property
var property = objectType.GetProperty(propertyName);
//check for object relation
return property.GetCustomAttributes().FirstOrDefault(x => x.GetType() == attrType);
}
var objectRelAttr = GetAttribute(typeof(Person), "Country", typeof(ObjectRelationAttribute));
var displayNameAttr = GetAttribute(typeof(Product), "Category", typeof(DisplayNameAttribute))