Lightweight AOP framework-porting Python decorator to C)

Source: Internet
Author: User
Tags python decorator
1. Start with Python

Python is a powerful language. It contains a lot of magical skills. As a dynamic language, its inherent advantages make it difficult to achieve many static languages. What we show today is a very useful feature in Python: "decorator", which can be translated as "decorator" in Chinese. So what is decorator?

In dr. Dobb'sArticleDecorators are Python objects that can register, annotate, and/or wrap a python function or object .".

Specifically, decorator is a function encapsulation that allows you to intervene in function execution without changing the function itself, such as permission authentication and logging before execution, you can even modify input parameters, pre-process the returned results after execution, or even intercept the execution of functions.

See if the definition has a certain degree of familiarity. That's right. In essence, it is what we often call Aspect-oriented programming (Aspect-Oriented Programming), or AOP for short, I believe everyone is familiar with AOP. Due to the advantages of dynamic language itself, this kind of technology can be used on Dynamic Language platforms.

Ii. Example of decorator in Python

After reading a lot of mysterious concepts, we will use a simple Python example to illustrate how to program decorator.

 def logger (name): def loggerwrapper (fun): def logging (Self ): print "user is % S. "% name print" start logging "result = fun (Self) print" End logging. "Return result return logging return loggerwrapperdef debugger (name): def debuggerwrapper (fun): def debugging (Self ): print "Debug % s" % name print "Start debug" result = fun (Self) print "End debug" return result return debugging return debuggerwrapperclass myclass (): @ logger ("Leven") @ debugger ("test") def test (Self): Print ("function myclass: test called. ") Return" I am reuslt. "If _ name _ =" _ main _ ": MC = myclass () print" Result: % s "% MC. test () 

 

Execute changeProgram, You can get the following results:

Looking back at the features of the program, we can see from the source code that the use of decorator is very simple. It can be placed directly before the function definition, and the system can identify it through @ xxx. The following describes some features of decorator.

    1. The essence of decorator is a function, which can have input parameters. It needs to return a function object (note the differences between the two functions). Therefore, in the program, the decorator named logger returns a function object named loggerwrapper. Similarly, the decorator named debugger returns a function object named debuggerwrapper, which is the first point defined by decorator: the decorator function must return a function object.
    2. The function objects returned by decorator are also required, because the returned function objects are executed when the system calls the function. Therefore, when the system calls this function object, it will pass in the currently decorated function object (note that this may not be the original defined function object ), at the same time, a function consistent with the modified function definition must be returned for the system to call. ComparisonCodeThe loggerwrapper function receives a fun parameter. Obviously, this parameter is the currently modified function object. At the same time, it returns the logging function object, the definition of this function is completely consistent with that of the modified function.
    3. When the system calls the modifier method, it actually executes the function object returned in the 2nd POint Description. That is to say, the system will steal the bar for the function, and the actual execution is not the original defined function body. Whether the defined function body is executed depends on the specific implementation of the decorator.
    4. For multiple decorator instances, the system performs the first two steps sequentially. At the same time, the system processes the decorator in reverse order.

Next we will explain the execution methods in the above example in sequence:

First, the system checks that the function test has a decorator. Because it is in reverse order, the system will directly execute debuggerwrapper for the debugger and pass test as the parameter fun, after the debuggerwrapper function is executed, the debugging function object is returned. Therefore, the system steals test from debugging. Therefore, if the test method is executed, the debugging method actually executed continues, there is also a logger modifier. Similarly, the system will directly execute the loggerwrapper function and run the current function (note that the current function is no longer test, because it is decorated by debuger, test has been replaced by debugging. Therefore, the debugging function object is passed in as the parameter fun. After the loggerwrapper method is executed, the logging function object is returned. The function definition is exactly the same as that of test, therefore, the system calls the debugging function ( Replace bugging with) with the logging function. Therefore, this function runs directly to the logging function during overall execution.

In the above example, the system calls the test function to actually execute the logging function. In the logging function, the fun (Self) actually calls debugging (Self), while the fun (Self) called in debugging) the test method is actually executed.

Iii. Think about it by referring to C #

Is it heart-warming to see such a simple and practical decorator? Find a way to enable C # to enjoy this benefit. In C #, attribute is similar to Python. Therefore, we consider using attribute and a series of related operations to simulate Python execution.

In C #, the function object is described by the delegate. Therefore, we consider that, similarly, let the attribute that supports the decorator operation implement a specific interface, which returns a delegate, then, the Delegate will be executed when the method is actually executed, so consider the following form:

 
Public class myclass {[logger ("Leven")] Public String test (string s) {XXX return XXX ;}} Public Delegate string testmethoddelegate (string S); public class loggerattribute: attribute {public string name {Get; private set;} public loggerattribute (string name) {name = Name;} testmethoddelegate loggerwrapper (testmethoddelegate fun) {Return e => {console. writeline ("user is {0 }. ", name); console. writeline ("start logging"); var result = fun (E); console. writeline ("End logging"); return result ;}}}

In this way, the form is roughly the same as the decorator of Python. However, under normal circumstances, C # does not automatically process the relationship between loggerattribute and test like python. Therefore, loggerwrapper can never be executed, let alone Replace the test method. Therefore, we need to continue to consider the implementation of specific functions.

IV. Implementation of functions

To implement the decorator, it is very important that the method can be "stolen", while C # Cannot modify the method during runtime. Of course, decorator is essentially a manifestation of AOP. Therefore, we can consider the common implementation methods of AOP. AOP generally has two implementation methods: Dynamic proxy and static weaving. Although dynamic proxy has some small limitations, it is much simpler to implement and use than static weaving. Therefore, we want to use dynamic proxy to implement this function.

For the myclass class, we want to generate a new myclasswrapper class that inherits from myclass. At the same time, we need to change the test method to the virtual method, we can rewrite the test method in the myclasswrapper class, so that we have achieved the "steal the bar" approach. Although it is not good enough than python, it is also very welcome to meet our requirements. Therefore, our myclasswrapper class requirements are defined as follows:

Public class myclasswrapper: myclass {public override string test () {loggerattribute attribute = typeof (myclass ). getmethod ("test "). getcustomattribute (typeof (loggerattribute), true) [0] As loggerattribute; // obtain the first loggerattribute in the base class // call the loggerwrapper method to obtain the new delegate. vaR fun = attribute. loggerwrapper (New testmethoddelegate (TEST); Return fun ();}}

In this way, the implementation of the test method is rewritten to achieve the same effect as the decorator in Python. However, this method of C # is different from that of Python. in Python, the decorator function replaces the decorator function, but in C, because the method cannot be replaced by another delegate object, we can only manually execute the decorated method within the method, but the effect is completely consistent. Of course, the above example only represents an implementation method. In the case of multiple attributes, many different processing operations are required. However, this means that python decorator can be fully implemented on C.

In the above example, we decorated the test method. However, as a framework, we require that all methods that meet the requirements can be decorated. Therefore, we need to modify the preceding implementation. It is very important that the decorator above can only process methods such as string test (string). If it is a string test (object), we need to redefine it, which is inconvenient to use, therefore, we consider using a common method signature to represent all method calls, that is, using func <object, object [], Object> to represent any method.

5. Summary

In this article, we thoroughly analyzed the principle of decorator in Python, and evaluated the feasibility of implementing the same decorator in C #. Through analysis, we can be sure that on C, through some technical means, we can fully implement the decorator function similar to Python.

In the next article, we will start with a specific practice and port Python decorator completely. Therefore, the next article will be named "encoding ".

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.