在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
//订单类
public class Order
{
public int Id { set; get; }
public string Name { set; get; }
public int Count { set; get; }
public double Price { set; get; }
public string Desc { set; get; }
}
//订单接口 抽象
public interface IOrderProcessor
{
//业务逻辑
void Submit(Order order);
}
//订单业务逻辑 实现
public class OrderProcessor : IOrderProcessor
{
public void Submit(Order order)
{
Console.WriteLine("提交订单");
}
}
//装饰器模式提供一个AOP功能 装饰器模式是23中设计模式种,结构型模式的巅峰之作,组合+继承
public class OrderProcessorDecorator : IOrderProcessor //继承=》接口
{
//订单业务逻辑属性 组合=》到内部
public IOrderProcessor OrderProcessor { get; set; }
//构造函数
public OrderProcessorDecorator(IOrderProcessor orderprocessor)
{
OrderProcessor = orderprocessor;
}
//1.继承业务逻辑接口的时候会实现业务逻辑
//2.使用组合进来的业务对象实现对应的业务逻辑
//3.在这个业务逻辑前后添加上自己想要的功能
//业务逻辑
public void Submit(Order order)
{
PreProceed(order);
OrderProcessor.Submit(order);
PostProceed(order);
}
//业务逻辑之前
public void BeforeProceed(Order order)
{
Console.WriteLine("提交订单前,进行订单数据校验....");
if (order.Price < 0)
{
Console.WriteLine("订单总价有误,请重新核对订单。");
}
}
//业务逻辑之后
public void AfterProceed(Order order)
{
Console.WriteLine("提交带单后,进行订单日志记录......");
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "提交订单,订单名称:" + order.Name + ",订单价格:" + order.Price);
}
}
static void Main(string[] args)
{
//订单类
Order order = new Order() { Id = 1, Name = "lee", Count = 10, Price = 100.00, Desc = "订单测试" };
//装饰器模式实现的静态代理
IOrderProcessor orderprocessor = new OrderProcessorDecorator(new OrderProcessor());
//调用,装饰器模式实现的静态代理,调用对应的业务逻辑
orderprocessor.Submit(order);
Console.ReadLine();
}
//订单类
public class Order
{
public int Id { set; get; }
public string Name { set; get; }
public int Count { set; get; }
public double Price { set; get; }
public string Desc { set; get; }
}
//订单接口
public interface IOrderProcessor
{
void Submit(Order order);
}
//订单业务逻辑
public class OrderProcessor : IOrderProcessor
{
public void Submit(Order order)
{
Console.WriteLine("提交订单");
}
}
//订单静态代理实现
public class OrderProcessorProxy : IOrderProcessor
{
//业务逻辑字段
private IOrderProcessor _OrderProcessor = new OrderProcessor();
//1.继承业务逻辑接口的时候会实现业务逻辑
//2.使用业务逻辑字段
//3.在这个业务逻辑前后添加上自己想要的功能
//业务逻辑
public void Submit(Order order)
{
PreProceed(order);
_OrderProcessor.Submit(order);
PostProceed(order);
}
public void PreProceed(Order order)
{
Console.WriteLine("提交订单前,进行订单数据校验....");
if (order.Price < 0)
{
Console.WriteLine("订单总价有误,请重新核对订单。");
}
}
public void PostProceed(Order order)
{
Console.WriteLine("提交带单后,进行订单日志记录......");
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "提交订单,订单名称:" + order.Name + ",订单价格:" + order.Price);
}
}
static void Main(string[] args)
{
//初始化订单类
Order order = new Order() { Id = 1, Name = "lee", Count = 10, Price = 100.00, Desc = "订单测试" };
//初始化代理模式实现的 AOP思想
IOrderProcessor orderProcessor = new OrderProcessorProxy();=======
orderprocessor.Submit(order);
Console.ReadLine();
}
//01接口 订单处理器接口
public interface IOrderProcessor
{
void Submit(Order order);
}
//02具体的实现类 订单处理器
//MarshalByRefObject 表示上下文的绑定对象,允许远程调用,可以访问边界=》一旦继承了这个类,那么整个类可以被我们序列化。
//把这块内存序列化成一个东西传到远程的机器,远程的机器再把东西序列化成一个别的东西,就可以调用这个对象,把调用的结果再传回来。
//核心:本地序列化=》远程=》远程再在收到的内容前后做AOP处理
public class OrderProcessor:MarshalByRefObject,IOrderProcessor
{
//03 实现接口
public void Submit(Order order)
{
Console.WriteLine("提交订单");
}
}
/// <summary>
/// 真实代理 固定写法
/// </summary>
/// <typeparam name="T"></typeparam>
public class MyRealProxy<T> : RealProxy
{
//04 将透明代理传进来的对象包装
private T tTarget;
public MyRealProxy(T target)
: base(typeof(T))
{
this.tTarget = target;
}
public override IMessage Invoke(IMessage msg)
{
//执行前
BeforeProceede(msg);
//调用原有方法
IMethodCallMessage callMessage = (IMethodCallMessage)msg;
object returnValue = callMessage.MethodBase.Invoke(this.tTarget,callMessage.Args);
//执行后
AfterProceede(msg);
return new ReturnMessage(returnValue,new object[0],0,null,callMessage);
}
public void BeforeProceede(IMessage message)
{
Console.WriteLine("方法执行前可以加入的逻辑");
}
public void AfterProceede(IMessage message)
{
Console.WriteLine("方法执行后可以加入的逻辑");
Console.ReadLine();
}
}
/// <summary>
/// 透明代理 固定写法
/// </summary>
public static class TransparentProxy
{
//03 创建对象
//0-1 给个类型
public static T Create<T>()
{
//0-2 创建一个对象
T instance = Activator.CreateInstance<T>();
//0-3 通过真实代理进行包装
MyRealProxy<T> realProxy = new MyRealProxy<T>(instance);
//0-4 得到一个新对象
T transparenProxy = (T)realProxy.GetTransparentProxy();
//0-5 返回一个新对象 新对象和它类型一致,是他的子类
return transparenProxy;
}
}
static void Main(string[] args)
{
Order order = new Order { Id = 1, Name = "苹果", Pirce = 20, Count = 2, Desc = "订单测试" };
OrderProcessor orderProcessor = TransparentProxy.Create<OrderProcessor>();
orderProcessor.Submit(order);
}
配置文件实现 代码实现 ,配置文件实现是代码中经常用到的
NuGet包引用
Prism.Unity
Unity.Configuration
Unity.Interception
Unity.Interception.Configuration
01 业务逻辑抽象 IUserBll
public interface Itest
{
void show();
}
02 业务逻辑实现
public class test : Itest
{
public void show()
{
Console.WriteLine("======================业务逻辑====================");
Console.WriteLine("这里是业务逻辑");
Console.WriteLine("======================业务逻辑====================");
}
}
03 引入Unity容器
static void Main(string[] args)
{
Print();
}
static void Print()
{
#region 引入Unity容器,这是一段固定写法 作用是读取当前应用程序运行目录下的Unity.Config配置文件,配置一个容器
//1. 初始化UnityContainer容器
IUnityContainer container = new UnityContainer();
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
//2. 开始读取配置文件
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
#endregion
//01 使用UnityConfigurationSection 配置(容器,名称)方法代替 配置容器 将容器和配置文件中的别名关联"
configSection.Configure(container, "aopContainer");
//02 通过容器创建对象
Itest processor = container.Resolve<Itest>();
//02 调用业务方法
processor.show();
}
04 设置配置文件
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
</configSections>
<unity>
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
<containers>
<container name="aopContainer">
<extension type="Interception"/>
<register type="AOP.Itest,AOP" mapTo="AOP.test,AOP">
<interceptor type="InterfaceInterceptor"/>
<interceptionBehavior type="AOP.MonitorBehavior,AOP"/>
<interceptionBehavior type="AOP.LogBehavior,AOP"/>
</register>
</container>
</containers>
</unity>
</configuration>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
</configSections>
<unity>
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
<containers>
<container name="aopContainer">
<extension type="Interception"/>
<register type="业务逻辑抽象命名空间,业务逻辑所在程序集" mapTo="业务逻辑,业务逻辑所在程序集">
<interceptor type="InterfaceInterceptor"/>
<interceptionBehavior type="AOP类名,AOP类所在程序集"/>
</register>
</container>
</containers>
</unity>
</configuration>
static void Print()
{
#region 引入Unity容器,这是一段固定写法 作用是读取当前应用程序运行目录下的Unity.Config配置文件,配置一个容器
//1. 初始化UnityContainer容器
IUnityContainer container = new UnityContainer();
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
//2. 开始读取配置文件
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
#endregion
//01 使用UnityConfigurationSection 配置(容器,名称)方法代替 配置容器 将容器和配置文件中的别名关联"
configSection.Configure(container, "aopContainer");
//02 通过容器创建对象
Itest processor = container.Resolve<Itest>();
//02 调用业务方法
processor.show();
}
public class LogBehavior : IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
#region 业务逻辑前执行
Console.WriteLine("\r\n");
Console.WriteLine("=================耗时统计=========================");
Console.WriteLine("正在记录日志,请稍后······");
#endregion
#region 分割线
var method = getNext().Invoke(input, getNext);
#endregion
#region 业务逻辑后执行
Console.WriteLine("=================耗时统计=========================");
#endregion
return method;
}
}
异常:
The type name or alias Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration could not be resolved.Please check your configuration file and verify this type name.
解决方法:
https://github.com/volador816/AOP
正是因为能动态的扩展功能,所以在程序设计时就可以有一下的好处:
思考:为什么需要AOP,AOP可以解决什么问题?
一个典型对象(静态,牢不可破)
属性:ID Name
行为:Study Eat
以来抽象:ISports
静态的固定整体,可以修改属性值,可以复写行为,可以替换抽象实现,但是类自身是稳定不变的
砖=》墙=》房间=》大厦
类=》功能点=》模块=》系统
如何理解静态?砖应该是稳定的,静态的,否则房子就不稳定。
遇到的问题:类却是会变化的,例如:增加日志/异常/权限/缓存/事务
是否只能修改类?
所以才有了GOF的23中设计模式,应对变化,设计模式的核心套路就是依赖抽象,细节就可以变化。
但是只能替换整个对象,但是没办法把一个类动态改变。
原文:https://www.cnblogs.com/fishpond816/p/14353526.html