. Net use proxy to implement AOP
In the previous article, I mentioned that exception handling can be encapsulated using generic delegation in the code, which makes the program look clearer. To complete the function, the caller must call the specified factory method, however, it is difficult for some programmers to change their coding habits. Some friends said that using delegation to implement exception handling is not really AOP, because traditional AOP does not require the client to make code structure changes, that is, the configuration problems at most. However, to implement AOP in. net, I think the most convenient implementation mechanism should belong to the proxy mechanism, but as long as the proxy is used, the performance will have a certain impact.
If you have developed distributed services, such as remotion and wcf, messages are important means for communication. The Service Access reflected by the client through method calls needs to be converted into a specific message, and then encoded before being sent to the server through the transmission channel, the service execution results can only be returned to the caller in the form of messages.
These distributed services share a common feature: services are called indirectly through proxy methods. The Service proxy itself does not provide service implementation, but serves as an intermediary. The client sends service requests to the Service proxy, and the Service proxy calls the real service again. When the service returns, it is also returned to the Service proxy and then returned to the client by the Service proxy. Seeing this, I think it is a little eye-catching to implement AOP interception. In. net, we can write a custom RealProxy to implement the method Interception Function of AOP.
Service proxies are generally divided into the following two types:
1: transparent proxy. When the client uses an object across any type of remote processing boundary, it actually uses a transparent proxy for the object. The transparent proxy enables the actual object to reside in the client space. The method is to forward the call made to a real object using the remote processing infrastructure. The transparent proxy itself is hosted by instances of the RealProxy-type runtime class. RealProxy implements some of the functions required for forwarding from a transparent proxy. Proxy objects inherit the association semantics of managed objects (such as garbage collection and support for members and methods) and can be extended to form a new class. In this way, the proxy has a dual nature. On the one hand, it needs to act as the same class object as the remote object (transparent proxy); on the other hand, it itself is a hosted object.
2: Real proxy. RealProxy to implement communication with remote services, so here is where we implement AOP.
Is the call relationship between the transparent proxy and the real proxy and remote objects:
Is a schematic diagram of Implementing AOP interception using a custom RealProxy:
Custom exception Proxy:
Note: 1> Custom proxy classes must inherit RealProxy.
2> when inheriting from RealProxy, you must override the Invoke method.
3> the LogManage in the following code is a log4net interface. We can record exceptions to logs for future analysis.
Code
/// <Summary>
/// Aspect proxy, which intercepts methods in this class
/// </Summary>
Public class AspectProxyErrorLog: RealProxy
{
AspectManagedAttribute attr;
/// <Summary>
/// Default constructor
/// </Summary>
Public AspectProxyErrorLog (): base ()
{
}
/// <Summary>
/// Constructor
/// </Summary>
/// <Param name = "myType"> type of the class to be proxy </param>
Public AspectProxyErrorLog (Type myType): base (myType)
{
}
/// <Summary>
/// Constructor
/// </Summary>
/// <Param name = "myType"> type of the class to be proxy </param>
/// <Param name = "obj"> proxy object </param>
Public AspectProxyErrorLog (Type myType, MarshalByRefObject obj): base (myType)
{
Target = obj;
}
MarshalByRefObject target;
ILog LogManage;
/// <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! = Ex. InnerException)
{
MethodReturn = new ReturnMessage (ex. InnerException, methodCall );
}
Else
{
MethodReturn = new ReturnMessage (ex, methodCall );
}
}
RetMsg = methodReturn;
}
If (null! = MethodReturn)
{
If (null! = MethodReturn. Exception)
{
If (null! = This. LogManage)
{
This. LogManage. Error (ceha. MethodErrorText + methodReturn. Exception. ToString ());
}
}
}
Return retMsg;
}
}
The above is just a part of the Code. In the next article, I will analyze this part of the code in more detail.
Author: Jiang min
Source: http://www.cnblogs.com/aspnet2008/