Remolding a server's data store with AOP

Source: Internet
Author: User
Tags aop emit throw exception managed hosting

Background is that there is a game server has been writing SQL, and later changed the Redis for a period of time, with the other staff write the class ORM way to map the entity type to various key-value to write, but there is still a drawback is the need to add \ Delete \ change when the explicit call API, What's worse is to indicate the name of the deleted \ changed field, otherwise the entire entity will be rewritten. In actual use often will appear to write wrong paragraph name, or rename the field after forgetting to modify the old field name string parameters, even forget to call the update API cause data not saved ... (The same happens when you write SQL)

In fact, the increment/delete/switch to the SQL or Reids API is very simple, can be automatically generated, eliminate the trouble of repeated writing and easy to write the wrong question.

As a result, I plan to save the changed attribute values by monitoring/intercepting the increment/delete/change method to automatically generate Sql/redis calls while the data is being modified. In fact, additions and deletions are relatively simple, as long as the customization of a collection type inherited under the Ienumerable<t> interface, and then implement the deletion method can be, the original code modification is also very small.

But it's a bit of a hassle, you need to intercept the property's set method, which is an AOP field that hasn't been used before.

After some surveys, I think there are two ways to be more suitable.

One is static weaving, that is, in the form of similar code templates, first write the entity type template, and then generate a real entity type Class library, at the time of generation modification in the property set method to inject the Propertychangednotify event, the service is using the generated entity class library. Postsharp looks good, but doesn't want to introduce more overhead. It might be nice to use T4 or emit.

The second is the dynamic, basically is to generate a proxy type, have all the original type of interface, but re-implemented again. Can be a combination of ways to save the original type instance as a private member, emit generate all the original types of open methods; It can also be inherited in a way that overloads. Considering the amount of modification to the original code, I think the inherited overloads are good.

For example, the original entity type is as follows:

 Public class person{    publicstring id{get;  Set;}      Public string name{get;  Set;} }

The implementation of this class to modify the managed hosting, it is not possible to use this type directly (unless schema 1 static modification injection), only using dynamically generated proxy entity classes, and if the use of the combination of proxy type, in the case of Oo very awkward, so I chose to inherit the overloaded way. This requires a modification of this entity type, which modifies all properties that need to be monitored into virutal declarations ctrl+h.

Then, because it is deleted and changed, so key is necessary, then the entity needs to mark the key attribute with attribute, support multi-attribute combination key. Because the original code used for a period of time entityframework, so this transformation is very smooth.

The final type is defined as follows:

[DataContract]  Public class person{    [Key]      publicstring id{get;  Set;}      Public Virtual string name{get;  Set;} }

First, mark the person with attribute as the type that needs to be proxied, make it easy to correct and preload in real-world use, then tag the id attribute as key, and do not require overloading, other attributes declared as virtual represent the need for overloading for monitoring.

Then handwriting a proxy type:

 Public classpersonproxy:person{ Public Override stringName {Set        {            Base. Name=value; Interceptor.invoke ( This,"Name", value); }    }  } Public Static classinterceptor{ Public Static voidInvoke (ObjectInstancestringNameObjectvalue) {        //Log    }}

Then define a static class of factory, implement the static generic function create<t> () to create the proxy type personproxy of the person. In fact, the latter is called the proxy type, just use the method and person consistent, compatible with the old code.

In this case, it is better to use static weaving. So the handwritten personproxy needs to be generated dynamically so that all custom classes are supported by generics, reducing frequent changes. So the emit appeared.

But I have a shallow understanding of IL and emit, and my approach is to use the VS own tool--ildasm, to open the personproxy I just generated to see the IL code, After repeated comparisons, the dynamic generation of this personproxy type is successfully implemented with emit and modified to generic. This special IL learning methodology is a proven and proven method. The method is so much so that the emit code is not posted here. Invoke weaving can also do a variety of evolution to achieve more advanced functions, such as invoke before assignment, write fail fallback throw exception, etc...

So the proxyfactory.create<t> () function is written.

Generating in invoke requires either SQL or Redis set method.

Finally implement add and delete Agent collection type, at the time of adding the inserted object directly through Proxyfactory.create<t> () to the proxy sub-class object, in order to avoid add after continue to use the incoming original object and lost to the property set monitoring, Modify the Add Declaration as add (ref T obj) to forcibly modify the reference as a proxy object. Eradicate from the entrance, perfect.

Theory OK, then encapsulated into a class library.

Finally put the code address:

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.