1. AOP
AOP : allows developers to dynamically modify the static OO model, just like real life objects constantly change their life cycle.
AOP is a programming idea is to add OOP ideas
1.1 AOP Aspect Oriented Programming
1.1.1 AOP has the following benefits
1.1.1.1 focus on core business logic
General functional competence / abnormal / log / cache / AOP affairs by way of adding simple programming,
1.1.1.2 features dynamic expansion
Centralized management, code reuse; standardization;
1.1.2 AOP to achieve a variety of ways
l static implementation - Decorator / proxy mode
l dynamic implementation --Remoting / Castle (Emit)
l Static weaving --PostSharp (surcharge) - extended compiler tool, added extra code generated
l dependency injection container AOP extended (developed)
L MVC Filter-- characteristic marker, and the method is performed before / after multiple logical
invoker call center - is responsible for calling the reflection method - checking feature - it has to perform additional logic
1.2 Static AOP implementation
Static AOP can be achieved by encoding the decorator pattern or proxy mode.
1.2.1 Decorator achieve
/// <summary>
/// Decorator achieve a static agent
/// </summary>
public class DecoratorAOP
{
public static void Show()
{
User user = new User()
{
Name = "Olive",
Password = "116"
};
IUserProcessor processor = new UserProcessor();
processor.RegUser(user);
Console.WriteLine("***********************");
processor = new UserProcessorDecorator(processor);
processor.RegUser(user);
}
public interface IUserProcessor
{
void RegUser(User user);
}
public class UserProcessor : IUserProcessor
{
public void RegUser(User user)
{
Console.WriteLine ($ "registered user, Name: {user.Name}, Password: {user.Password}");
}
}
/// <summary>
/// decorator pattern to provide an AOP functionality
/// </summary>
public class UserProcessorDecorator : IUserProcessor
{
private IUserProcessor _UserProcessor { get; set; }
public UserProcessorDecorator(IUserProcessor userProcessor)
{
this._UserProcessor = userProcessor;
}
public void RegUser(User user)
{
BeforeProceed(user);
this._UserProcessor.RegUser(user);
AfterProceed(user);
}
private void BeforeProceed(User user)
{
Console.WriteLine ( "before the method is performed");
}
private void AfterProceed(User user)
{
Console.WriteLine ( "After the implementation of the method");
}
}
}
1.2.2 proxy mode to achieve
/// <summary>
/// proxy mode to achieve the static agent
/// AOP method of increasing method before and after the custom
/// </summary>
public class ProxyAOP
{
public static void Show()
{
User user = new User()
{
Name = "XF",
Password = "1165"
};
IUserProcessor processor = new UserProcessor();
processor.RegUser(user);
Console.WriteLine("****************************");
processor = new ProxyUserProcessor();
processor.RegUser(user);
}
public interface IUserProcessor
{
void RegUser(User user);
}
public class UserProcessor : IUserProcessor
{
public void RegUser(User user)
{
Console.WriteLine ($ "registered user, Name: {user.Name}, Password: {user.Password}");
}
}
/// <summary>
/// proxy mode to provide an AOP functionality
/// </summary>
public class ProxyUserProcessor : IUserProcessor
{
private IUserProcessor _UserProcessor = new UserProcessor();
public void RegUser(User user)
{
BeforeProceed(user);
this._UserProcessor.RegUser(user);
AfterProceed(user);
}
private void BeforeProceed(User user)
{
Console.WriteLine ( "before the method is performed");
}
private void AfterProceed(User user)
{
Console.WriteLine ( "After the implementation of the method");
}
}
}
1.3 dynamic proxy AOP implementation
It may be achieved by dynamic AOP Remoting / Castle (Emit).
1.3.1 Remoting achieve
/// using .Net Remoting / RealProxy dynamic agent
/// limitations must be inherited from MarshalByRefObject type of business class
public class RealProxyAOP
{
public static void Show()
{
User user = new User()
{
Name = "XF",
Password = "116"
};
UserProcessor processor = new UserProcessor();
processor.RegUser(user);
Console.WriteLine("************************");
UserProcessor userProcessor = TransparentProxy.Create<UserProcessor>();
userProcessor.RegUser(user);
}
public interface IUserProcessor
{
void RegUser(User user);
}
public class XFRealProxy<T> : RealProxy
{
private T t;
public XFRealProxy(T target) : base(typeof(T))
{
this.t = target;
}
public override IMessage Invoke(IMessage msg)
{
BeforeProceede(msg);
IMethodCallMessage callMessage = (IMethodCallMessage)msg;
object returnValue = callMessage.MethodBase.Invoke(this.t, callMessage.Args);
AfterProceede(msg);
return new ReturnMessage(returnValue, new object[0], 0, null, callMessage);
}
public void BeforeProceede(IMessage msg)
{
Console.WriteLine ( "logic may be added prior to performing the method");
}
public void AfterProceede(IMessage msg)
{
Console.WriteLine ( "Method performed after addition of logic");
}
}
public static class TransparentProxy
{
public static T Create<T>()
{
T instance = Activator.CreateInstance<T>();
XFRealProxy<T> realProxy = new XFRealProxy<T>(instance);
T transparentProxy = (T)realProxy.GetTransparentProxy();
return transparentProxy;
}
}
/// <summary>
/// inherit MarshalByRefObject parent class, in applications that support remoting, allowing access across application domain boundaries objects.
/// </summary>
public class UserProcessor : MarshalByRefObject, IUserProcessor
{
public void RegUser(User user)
{
Console.WriteLine ($ "the user is registered, the user name {user.Name}, password: {user.Password}");
}
}
}
1.3.2 Castle achieve
/// <summary>
/// Use Castle \ DynamicProxy dynamic agent
/// method is a virtual method
/// </summary>
public class CastleProxyAOP
{
public static void Show()
{
User user = new User()
{
Name = "XF",
Password = "12345"
};
ProxyGenerator generator = new ProxyGenerator();
XFInterceptor interceptor = new XFInterceptor();
UserProcessor userProcessor = generator.CreateClassProxy<UserProcessor>(interceptor);
userProcessor.RegUser(user);
}
public interface IUserProcessor
{
void RegUser(User user);
}
public class UserProcessor : IUserProcessor
{
public virtual void RegUser(User user)
{
Console.WriteLine ($ "User Registration, Name {user.Name}, Password {user.Password}");
}
}
public class XFInterceptor:IInterceptor
{
public void Intercept(IInvocation invocation)
{
PreProceed(invocation);
invocation.Proceed (); // call the original business methods
PostProceed(invocation);
}
public void PreProceed(IInvocation invocation)
{
Console.WriteLine ( "before the method is performed");
}
public void PostProceed(IInvocation invocation)
{
Console.WriteLine ( "After the implementation of the method");
}
}
}
1.4 Unity, MVC in AOP
1.4.1 Unitiy achieve AOP
You want to reference the following components in NuGet in:
Unity、Unity.Interception、Unity.Configuration
Unity.Interception.Configuration
1.4.1.1 IUserProcessor
Defined interfaces
public interface IUserProcessor
{
void RegUser(User user);
User GetUser(User user);
}
1.4.1.2 User Processor
Interface implementation class
public class UserProcessor:IUserProcessor
{
public void RegUser(User user)
{
Console.WriteLine ( "Register");
}
public User GetUser(User user)
{
return user;
}
}
1.4.1.3 MonitorBehavior
Performance testing method for adding AOP
public class MonitorBehavior: Unity.Interception.InterceptionBehaviors.IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine(this.GetType().Name);
string methodName = input.MethodBase.Name;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var methodReturn = getNext().Invoke(input, getNext);
stopwatch.Stop();
Console.WriteLine ($ "{this.GetType () Name.} {MethodName} statistical method performed Processed {stopwatch.ElapsedMilliseconds} ms");
return methodReturn;
}
}
1.4.1.4 LogBeforeBehavior
AOP add logging method
public class LogBeforeBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("LogBeforeBehavior");
foreach(var item in input.Inputs)
{
Console.WriteLine(item.ToString());
}
return getNext().Invoke(input, getNext);
}
1.4.1.5 ParameterCheckBehavior
Parameter Check method AOP added
public class ParameterCheckBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior
{
public bool WillExecute { get { return true; } }
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("ParameterCheckBehavior");
User user = input.Inputs[0] as User;
if (user.Password.Length < 3)
return input.CreateExceptionMethodReturn (new Exception ( "Password length not less than 3"));
else
{
Console.WriteLine ( "correct detection parameter");
return getNext().Invoke(input, getNext);
}
}
}
1.4.1.6 CachingBehavior
Added caching method AOP
public class CachingBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("CachingBehavior");
if (input.MethodBase.Name.Equals("GetUser"))
return input.CreateMethodReturn(new User() { Id = 116, Name = "XF" });
return getNext().Invoke(input, getNext);
}
}
1.4.1.7 ExceptionLoggingBehavior
Abnormal recording method AOP added
public class ExceptionLoggingBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("ExceptionLoggingBehavior");
IMethodReturn methodReturn = getNext().Invoke(input, getNext);
if (methodReturn.Exception == null)
Console.WriteLine ( "no anomaly");
else
Console.WriteLine($"异常:{methodReturn.Exception.Message}");
return methodReturn;
}
}
1.4.1.8 LogAfterBehavior
AOP add logging method
public class LogAfterBehavior : Unity.Interception.InterceptionBehaviors.IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("LogAfterBehavior");
foreach(var item in input.Inputs)
{
Console.WriteLine(item.ToString());
}
IMethodReturn methodReturn = getNext().Invoke(input, getNext);
Console.WriteLine("LogAfterBehavior" + methodReturn.ReturnValue);
return methodReturn;
}
}
1.4.1.9 UnityConfigAOP
public class UnityConfigAOP
{
public static void Show()
{
User user = new User()
{
Name = "XF",
Password = "116"
};
#region configuration UnityContainer (universal code)
IUnityContainer container = new UnityContainer();
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection configurationSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
configurationSection.Configure(container, "AOPContainer");
#endregion
IUserProcessor processor = container.Resolve<IUserProcessor>();
processor.RegUser(user);
processor.GetUser(user);
}
}