What is a feature
Definition of properties: The common language runtime allows the addition of keyword like description declarations called attributes, which annotate elements in a program, such as types, fields, methods, and attributes. The attribute and. Metadata from the NetFramework files is kept together and can be used to describe your code at runtime or to influence the behavior of your application while it is running.
How do I write custom features
To help you understand custom features, let’s first take a look at what the compiler does when a custom feature is applied to a particular part of your code. For example, to verify a Model, let’s declare a C# property like this
public class User
{
/// <summary>/ / / / / / name</summary>public string Name { get; set; } / / /<summary>/ / / mail / / /</summary>[EmailAttribute] public string Email { get; set; } / / /<summary>/ / / / / / salary</summary>[LenghtAttribute(10000, 100000)] public decimal Salary { get; set; }}Copy the code
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = = false, Inherited = false)] public class LenghtAttribute { private int _minLenght = 0; private int _maxLenght = 0; public LenghtAttribute(int minLenght, int maxLenght) { _minLenght = minLenght; _maxLenght = maxLenght; }}Copy the code
When the compiler finds that a FiedlName Attribute is applied to this Attribute, it first appends a string Attribute to the name, creating the combined name FieldNameAttribute, and then searches all namespaces of the path for classes that have that name specified, but notice, If the compiler finds a feature that marks an item and the name ends with an Attribute, the compiler will not add that character to the combination name. So that’s why we’re labeling fields with properties and the compiler will default to the Attribute character in a light blue font and then the compiler will find a class that has that name, and that class is derived directly or indirectly from System.attribute. The compiler also considers this class to contain information that controls the use of the property. In particular,
- Which types of program elements can be applied to
- Whether it can be applied to the same program element more than once
- Property, when applied to a class or interface, is inherited by a derived class and interface
- What are the required and optional parameters for this feature
If the specified property class is not found, or if a property class is found but the way the property is used does not match the information in the property class, the compiler will produce an error. For example, if the property class specifies that the property applies only to structures, but we apply it to fields or classes, the compiler will produce a compilation error
1. Specify the AttributeUsage class
First of all, The attribute class itself is tagged with an attribute, system.AttributeUsage, which indicates which type of program elements the attribute can be applied to. This parameter is mandatory under AttributeUsage and the type is enumerated AttributeTargets. Specific as follows
1.Assembly = 0x1,
2.Module = 0x2,
3.Class = 0x4,
4.Struct = 0x8,
5.Enum = 0x10,
6.Constructor = 0x20,
7.Method = 0x40,
8.Property = 0x80,
9.Field = 0x100,
10.Event = 0x200,
11.Interface = 0x400,
12.Parameter = 0x800,
13.Delegate = 0x1000,
14.ReturnValue = 0x2000,
15.GenericParameter = 0x4000,
16.All = 0x7FFF
If you want to know what types enumerations correspond to, you can go to System.AttributeTargets, so I’m not going to go into them but you should note that in the above enumeration type there are two enumerations that don’t correspond to any program elements, The Assembly and Module features can be applied to an entire Assembly or Module, rather than to a single element in the code. In this case, the feature can be placed anywhere in the source code, but requires the use of Assembly and Module
public class User
{
[Assembly: FieldNameAttribute(Parameters)]
[Module: FieldNameAttribute(Parameters)]
}
Copy the code
There are also two properties AllowMultiple and Inherited AllowMultiple that indicate whether the property can be applied to the same item more than once, Inherited means that a feature applied to a class or interface automatically applies to all derived classes and interfaces, and, if applied to methods and properties, to overridden versions of those methods and properties.
2. Specify characteristic parameters
Now I’ll show you how to customize the parameters that a feature accepts. The compiler checks the arguments passed to the property and looks for constructors in the property with those argument types. If the compiler finds such a constructor, the compiler passes the specified metadata to the assembly; otherwise, a compilation error is generated.
3. Optional parameters of the specified feature
In the AttributeUsaege attribute, you can add optional parameters to the attribute using another syntax that specifies the name and value of the optional parameters, and it works through the common attributes and fields in the attribute class.
Four, complete code
public abstract class BaseAttribute : Attribute
{
/// <summary>/ / / validation / / /</summary>
/// <param name="oValue"></param>
/// <returns></returns>
public abstract bool Validate(object oValue);
}
Copy the code
/// <summary>// feature extension ///</summary>
public static class AttributeExtend
{
/// <summary>/ / / validation / / /</summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public static bool Validate<T>(T t) { Type type = t.GetType(); foreach (var prop in type.GetProperties()) { if (prop.IsDefined(typeof(BaseAttribute), true)) { var oValue = prop.GetValue(t, null); Foreach (BaseAttribute item in prop.getCustomAttributes (typeof(BaseAttribute), true))// Get all attributes of the field {if (! item.Validate(oValue)) { return false; } } } } return true; }}Copy the code
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = = false, Inherited = false)]
public class LenghtAttribute : BaseAttribute
{
private int _minLenght = 0;
private int _maxLenght = 0;
public LenghtAttribute(int minLenght, int maxLenght)
{
_minLenght = minLenght;
_maxLenght = maxLenght;
}
public override bool Validate(object oValue)
{
decimal.TryParse(oValue.ToString(), out var minParam);
decimal.TryParse(oValue.ToString(), out var maxParam);
if (oValue != null)
{
return minParam >= _minLenght && maxParam <= _maxLenght;
}
return true;
}
}
Copy the code
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = = false, Inherited = false)]
public class EmailAttribute : BaseAttribute
{
public override bool Validate(object oValue)
{
if (oValue != null)
{
Regex r = new Regex(@"^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$");
return r.IsMatch(oValue.ToString());
}
return true;
}
}
Copy the code
Static void Main(string[] args) {var user = new user {Name = "1 ", Email = "[email protected]", Salary = 60000.1M}; var result = AttributeExtend.Validate<User>(user); Console.WriteLine("Hello World!" ); Console.ReadKey(); }Copy the code
If there is something not very clear or there are mistakes, welcome to correct if you like it might as well click a like collection