Implement AOP in. net (2)

Source: Internet
Author: User

In the previous article, I probably talked about how to use a custom proxy class in. net to implement AOP. That article mainly talked about some principles. In this article, we will go directly to the code.

 

1. AspectManagedAttribute feature.When it comes to the proxy mechanism, it should directly target a class rather than a specific method. Therefore, the minimum unit for Implementing AOP is the class. We define an AspectManagedAttribute feature, it identifies a specific class to be managed by AOP.

Note:

1: Because this feature allows identification on the Class, you need to add [AttributeUsage (AttributeTargets. Class)].

2: AOP can implement multiple non-business logic "". Here we add an enumeration aspectmanagedattritype type to AspectManagedType. There are two types:

1 ": common exception capture. When the request method throws an exception, it is recorded in the log and an empty object is returned.
2: Add a method call time record based on common exception capture.

Public enum AspectManagedType
{
ErrorHandle,
ElapsedTime
}

3 ": Inherit ProxyAttribute: indicates that the object type requires a custom proxy.

4 ": override ProxyAttribute method: externalbyrefobject CreateInstance (Type serverType ). Create different custom proxy classes based on different aspectmanagedtypes.

Code

Public override implements albyrefobject CreateInstance (Type serverType)
{
Export albyrefobject mobj = base. CreateInstance (serverType );
If (aspectManaged)
{
RealProxy realProxy = this. GetCurrentRealProxy (this. aspectManagedType, serverType, mobj );
Export albyrefobject retobj = realProxy. GetTransparentProxy () as your albyrefobject;
Return retobj;
}
Else
{
Return mobj;
}

}
Private RealProxy GetCurrentRealProxy (AspectManagedType _ aspectManagedType, Type serverType, MarshalByRefObject mobj)
{
RealProxy real = null;
If (AspectsManager. AspectsProxy. ContainsKey (serverType. Name ))
{
Return AspectsManager. AspectsProxy [serverType. Name];
}
Switch (_ aspectManagedType)
{
Case AspectManagedType. ElapsedTime:
Real = new AspectProxyElapsedTime (serverType, mobj );
Break;
Case AspectManagedType. ErrorHandle:
Real = new AspectProxyErrorLog (serverType, mobj );
Break;
Default:
Real = new AspectProxyErrorLog (serverType, mobj );
Break;
}
Lock (AspectsManager. AspectsProxy)
{
AspectsManager. AspectsProxy. Add (serverType. Name, real );
}
Return real;
}

 

5: Put all CustomProxy into static variables, which has a small performance improvement. Here we have created AspectsManager. The code is simple and only contains one manager container.

Public class AspectsManager
{
Public static Dictionary <string, RealProxy> AspectsProxy = new Dictionary <string, RealProxy> ();
}

 

2. Implementation of custom proxy classesHere I will post the AspectProxyErrorLog for exception handling:

Note:

1: You need to inherit from RealProxy, which provides the basic functions of proxy.
2: override the IMessage Invoke (IMessage msg) of RealProxy, and call the method specified in the provided IMessage for the remote object represented by the current instance.

Code

/// <Summary>
/// When re-writing in a derived class, the remote object indicated by the current instance is used in the method specified in the provided IMessage. <Br/>
/// WebsharpAspect intercepts the method Execution here
/// </Summary>
/// <Param name = "msg"> IMessage, containing information about method calls. </Param>
/// <Returns> the message returned by the method called, including the return value and all out or ref parameters. </Returns>
Public override IMessage Invoke (IMessage msg)
{
IMessage retMsg = null;
IMethodCallMessage methodCall = (IMethodCallMessage) msg;
IMethodReturnMessage methodReturn = null;
Object [] copiedArgs = Array. CreateInstance (typeof (object), methodCall. Args. Length) as object [];
MethodCall. Args. CopyTo (copiedArgs, 0 );
Object [] attrs = null;
CoustomerErrorHandleAttribute ceha = null;
If (msg is IConstructionCallMessage)
{
IConstructionCallMessage ccm = (IConstructionCallMessage) msg;
RemotingServices. GetRealProxy (target). InitializeServerObject (ccm );
ObjRef oRef = RemotingServices. Marshal (target );
RemotingServices. Unmarshal (oRef );
RetMsg = EnterpriseServicesHelper. CreateConstructionReturnMessage (ccm, (MarshalByRefObject) this. GetTransparentProxy ());
}
Else
{
IMethodCallMessage mcm = (IMethodCallMessage) msg;
Attrs = methodCall. MethodBase. GetCustomAttributes (typeof (CoustomerErrorHandleAttribute), false );
Ceha = LogManagerFactory. GetCoustomerErrorHandleAttribute (attrs, methodCall. MethodBase. Name );
If (null! = Ceha)
{
LogManage = ceha. ILogName;
}
Try
{
Object returnValue = methodCall.MethodBase.Invoke(this.tar get, copiedArgs );
MethodReturn = new ReturnMessage (returnValue, copiedArgs, copiedArgs. Length, methodCall. LogicalCallContext, methodCall );

}
Catch (Exception ex)
{
If (null! = This. LogManage)
{
This. LogManage. Error (ceha. MethodErrorText + ex. ToString ());
}
MethodReturn = new ReturnMessage (null, methodCall );
}
RetMsg = methodReturn;
}
Return retMsg;
}

3: When an exception is caught, the exception information is first written to the log. To prevent the method from throwing an exception, we can process the returned information so that it can directly return null. I don't know if this is appropriate. I 'd like to give you more comments.

Third: ContextBoundObject:Defines the base classes of all context-bound classes. Here we can create an empty class and inherit from ContextBoundObject. The client class only needs to be inherited.
 

Public abstract class AspectObject: ContextBoundObject
{
}


4. Client call.

1:

[AspectManaged (aspectManagedType = AspectManagedType. ErrorHandle)]
Public class GetMemberInfoProxy: AspectObject

 

2: if there are many projects and we want to record logs to different locations, we will often create multiple ILog interfaces. Here we can start up and down the methods, create a method-level CoustomerErrorHandle. It mainly provides the following attributes:

1>: public ILog ILogName {get; set;} provides custom log interfaces. Of course, ILog cannot be reflected in Atttribute. We can use enumeration to replace it, And then dynamically create the ILog interface on the backend.
2>: public string MethodElapsedTimeText {get; set;} indicates the time consumed by the method. If this parameter is not specified, the method name is used by default.
3>: public string MethodErrorText {get; set;} prompts when an exception occurs. If this parameter is not specified, the method name is used by default.

3: method-level example:

[CoustomerErrorHandle (MethodElapsedTimeText = "when reading member information based on membership card numbers:", MethodErrorText = "An error occurred while reading member information based on membership card numbers:")]
Public MemberInfo GetMemberInfo (long cardNo)

 

Summary:

I have tested the performance of AOP in this article, but I have not found much consumption. What do you think about the performance of AOP.

 

Author: Jiang min
Source: http://www.cnblogs.com/aspnet2008/

 

 

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.