Recently, I have succeeded in 「 Front end leader 」 Into the C# The pit of ( Actually, the front-end leader started from cocos turn unity The game developed )
One day ,「 Front end leader 」 After seeing this code, I asked a question :[ This is a decorator ]?
[HttpGet]
public Response Get() {
return ...
}
My first reaction was not , This thing is C# It's called in Chinese “ characteristic ”( English name Attribute, Hereinafter collectively referred to as features ), stay Java Middle call annotation , Although the writing and Python/TypeScript It's about the same , But the implementation method should be different in the impression .
But what we study in science and engineering is to be rigorous , You can't just rely on experience and feeling , So , I checked the information , I read the recommendation of Yangxu 《C# in nutshell》 This book , It not only confirms the answer to this question , Also on the Attribute With more information .
“ characteristic ”、 Decorator , In fact, they are all decorator patterns in design patterns , It's also AOP thought .
AOP yes Aspect Oriented Programming, That is, face-to-face programming .
AOP Break the system down into different concerns , Or it's called a section (Aspect), It's a kind of At run time , Dynamically cuts code into the specified method of the class 、 Programming ideas at specified locations
For example, there is now a website , There are shopping 、 social contact 、 Games and other functions are open to all users , It is now necessary to restrict the use of several of these functions only by senior members , We can add... To each module if Judge , But it's too intrusive , And will cause a lot of duplicate code ; Switch to AOP The way is to use decorators , Just add restrictions where senior members are needed ~
Let's first look at the differences in grammar
First look at it. Python Decorator in , stay Python The middle function is a first-class citizen , Decorator is also a function , Another function is embedded inside
def outer(func):
def inner():
# ... Some codes
result = func()
return result
return inner
When you use it
@outer
def test():
print('test')
Usage grammar and Java The same as the notes , With @ start
Actually, this is a grammar sugar , The actual effect is equivalent to
outer(test)
take test
Function is passed to decorator as an argument , The execution sequence of this code is as follows :
def outer(func)
: Decorator definition @outer
: Decorator grammar sugar , Direct execution outer
function , take test
Function passed in as argument outer
: Execute decorator syntax rules , take test
Replace function with inner
function inner
: perform inner
function code test
: according to inner
This line of code in :result = func()
, perform test
function code stay Python In this dynamic language , Implementing decorator patterns is really easier than static languages , The decorated content is passed into the decorator as a parameter , Decorators can directly access the decorated content for some processing .
C# in ,“ characteristic ” Is a class , Inherited from Attribute
class , Then you can include any attribute fields you want
use AttributeUsage
Characteristics of modified , You can specify which code elements this feature can decorate
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DemoAttribute : Attribute {
public DemoAttribute(string param1) {
this.param1 = param1;
}
public string param1 { get; set; }
}
Parameters in construction method , Is the parameter passed in when using the feature , Such as this :
[DemoAttribute("class")]
public class DemoClass {
[Demo("method")]
public void Method1() {
}
}
PS: You can omit the following when using the feature "Attribute", therefore
DemoAttribute
andDemo
It's the same thing
This will not produce any effect after writing
Because the characteristic is only a simple decoration
When the code is running ,C# The compiler instantiates DemoAttribute
This class , And then instantiate DemoClass
This class , And in DemoAttribute
You can't get the decorated content inside .
In order to make the decoration effective , You need to use reflection in combination ~
Reflection means that a program can access 、 The ability to detect and modify its own state or behavior .
Through the following code, you can get the decoration in DemoClass
Characteristics of
var info = typeof(DemoClass);
var attributes = info.GetCustomAttributes(true);
The decorated method can be obtained through the following code , And decoration parameters
foreach (var methodInfo in typeof(DemoClass).GetMethods()) {
var attribute = (DemoAttribute) Attribute.GetCustomAttribute(methodInfo, typeof(DemoAttribute));
if (attribute != null)
Console.WriteLine(" Method {0} Be decorated , Decoration parameters {1}", methodInfo.Name, attribute.param1);
}
After getting this information , Some more processing is done through other functions provided by reflection , That's what we call AOP
therefore ,C# Characteristics and Python/TypeScript Decorator in , Although the writing and usage are different , But all the same , The goals to be achieved are indeed similar .
But it is not rigorous to say the same thing , So it should be the same thing , But they are all implemented in their own languages AOP The way .