Introduction
If we had this right now in this example I will use as simple a logic as possible to implement all the functional requirements, which will highlight the core issues we are addressing. Example is a simple calculator class:
public class Calculator
{
public int Add (int x, int y) {return x + y;}
}
This class is simple enough, but if you think of it as a potentially more complex business processing class, you will face more details than the core functionality, such as permission control, audit log, performance monitoring, buffering, transactional environment, and so on. For simplicity, we first increase the logging functionality for this class, which requires that the invocation and processing results for each method be output to the console, as follows:
public class Calculator
{
public int Add (int x, int y)
{
Console.Write ("Add ({0},{1})", X, y);
int result = x + y;
Console.WriteLine ("= {0}", result);
return result;
}
}
It's easy, isn't it? Now we need to implement performance monitoring for this method, as follows:
public class Calculator
{
public int Add (int x, int y)
{
Console.Write ("Add ({0},{1})", X, y);
DateTime timebegin = System.DateTime.Now;
int result = x + y;
TimeSpan Timeinter =system.datetime.now-timebegin;
Console.Write ("[{0}]", timeinter);
Console.WriteLine ("= {0}", result);
return result;
}
}
At this point you have sensed that, although we have achieved the required functionality, we have stacked different code in one method for dealing with various issues. While in this simple example you won't feel any discomfort, imagine what happens if we add a second method to the class:
public class Calculator
{
public int Add (int x, int y)
{
Console.Write ("Add ({0},{1})", X, y);
DateTime timebegin = System.DateTime.Now;
int result = x + y;
TimeSpan Timeinter =system.datetime.now-timebegin;
Console.Write ("[{0}]", timeinter);
Console.WriteLine ("= {0}", result);
return result;
}
public int subtract (int x, int y)
{
Console.Write ("Subtract ({0},{1})", X, y);
DateTime timebegin = System.DateTime.Now;
int result = x-y;
TimeSpan Timeinter =system.datetime.now-timebegin;
Console.Write ("[{0}]", timeinter);
Console.WriteLine ("= {0}", result);
return result;
}
}
It's not a good idea to have duplicate code in two methods-think about if there are 10 methods in our calculator? What if we still have dozens of other classes like the calculator class? If we have more method-level features to implement (Rights control, transaction management ...) )? This is a recurring problem in enterprise application development. For clarity, we break the problem down into two parts, the first of which is the confusion of code responsibilities, followed by the repetition of the same code logic-problems that lead to difficulties in development management, code writing, and maintenance.
Solution One: Manually write your own agent solution
1, first we define the interface ICalculator:
Using System;
Namespace Proxy
{
public interface ICalculator
{
int Add (int x, int y);
int subtract (int x, int y);
}
}
2, the implementation of a specific interface:
Using System;
Namespace Proxy
{
public class Calculator:icalculator
{
public virtual int Add (int x, int y)
{
int result = x + y;
return result;
}
public virtual int subtract (int x, int y)
{
int result = x-y;
return result;
}
}
}
3, write to increase the log and performance detection function of the proxy class
Increase the function of logging, that is, functional requirements will output the invocation and processing results of each method to the console, and increase performance monitoring.
There are two implementations that annotate one of these
Using System;
Namespace Proxy
{
<summary>
Summary description of the calproxy.
</summary>
public class Calproxy:icalculator
// {
Private Calculator _calculator;
Public Calproxy ()
// {
This._calculator=new Calculator ();
// }
Private DateTime timebegin = System.DateTime.Now;
private void predosomething (int x, int y)
// {
Timebegin = System.DateTime.Now;
Console.Write ("Number ({0},{1}) \ n", x, y);
// }
Implement add
public virtual int Add (int x, int y)
// {
This. Predosomething (X,y);
int result = This._calculator.add (x,y);
This. Postdosomething (result);
return result;
// }
Implement Sub
public virtual int subtract (int x, int y)
// {
This. Predosomething (X,y);
int result = This._calculator.subtract (x,y);
This. Postdosomething (result);
return result;
// }
private void postdosomething (int result)
// {
TimeSpan Timeinter =system.datetime.now-timebegin;
Console.Write ("Run time [{0}]\n", timeinter);
Console.WriteLine ("Run results = {0}\n", result);
// }
// }
<summary>
Summary description of the calproxy.
</summary>
public class Calproxy:calculator
{
Public Calproxy ()
{}
Private DateTime timebegin = System.DateTime.Now;
private void predosomething (int x, int y)
{
Timebegin = System.DateTime.Now;
Console.Write ("Number ({0},{1}) \ n", x, y);
}
Implement add
public override int Add (int x, int y)
{
This. Predosomething (X,y);
int result = base. ADD (X,y);
This. Postdosomething (result);
return result;
}
Implement Sub
public override int Subtract (int x, int y)
{
This. Predosomething (X,y);
int result = base. Subtract (x,y);
This. Postdosomething (result);
return result;
}
private void postdosomething (int result)
{
TimeSpan Timeinter =system.datetime.now-timebegin;
Console.Write ("Run time [{0}]\n", timeinter);
Console.WriteLine ("Run results = {0}\n", result);
}
}
}
4, outside the calling mode
ICalculator ical=new proxy.calproxy ();
Ical.add (5,3);
Ical.subtract (7,2);
Results of running the program:
Number (5,3)
Run time [00:00:02.0156250]
Run result = 8
Number (7,2)
Run time [00:00:03]
Run result = 5
Scenario Two: Achieve Iinterceptor resolution by using Castle.dynamicproxy
Step 1,2 and problem solving
3, to achieve standardinterceptor, increase the log and performance monitoring functions
Standardinterceptor is an implementation class of interface Iinterceptor, we implement Standardinterceptor
Using System;
Using System.Collections;
Using Castle.dynamicproxy;
Namespace Proxy
{
<summary>
Proxyinterceptor Interceptor enables logging and performance monitoring
</summary>
public class Proxyinterceptor:standardinterceptor
{
Private System.DateTime Timebegin=system.datetime.now;
Public Proxyinterceptor ()
{}
protected override void Postproceed (Iinvocation invocation, ref object returnvalue, params object[] arguments)
{
TimeSpan Timeinter =system.datetime.now-timebegin;
Console.Write ("Run time [{0}]\n", timeinter);
Console.WriteLine ("Run result = {0}\n", returnvalue);
Base. Postproceed (invocation, ref returnvalue, arguments);
}
protected override void Preproceed (iinvocation invocation, params object[] args)
{
Console.Write ("Number ({0},{1}) \ n", Args[0], args[1]);
Timebegin=system.datetime.now;
Base. Preproceed (invocation, args);
}
public override Object Intercept (iinvocation invocation, params object[] args)
{
Preproceed (invocation, args);
Object RetValue = invocation. Proceed (args);
Postproceed (invocation, ref retvalue, args);
return retvalue;
}
}
}
4, using Castle.dynamicproxy call
Proxygenerator generator = new Proxygenerator ();
Object proxy = generator. Createclassproxy (typeof (Calculator), New Proxyinterceptor ());
ICalculator Icalcastle=proxy as ICalculator;
Icalcastle.add (5,3);
Icalcastle.subtract (7,2);
Implementation process: First completes a proxy class through code generation that inherits from the class to be woven. It then overrides the method to intercept in the proxy class, encapsulates the invocation object in the overridden method, and passes the Intercept method to the Intercepter object that the user passed in. In order to intercept, The Intercept method calls the preprocess of Intercepter, delegate the Intercepter method by invocation The callback function that the incoming postprocess points to.
Significance
In the AOP domain, you can implement additional functions such as logs, transactions, caching, and so on.