IOC与DI+面向切面编程AOP_面向切面编程

1 IOC控制反转和DI依赖注入

1.1 定义及作用

DIP 依赖倒置原则:系统架构时,高层模块不应该依赖低模块,二者通过抽象来依赖

依赖抽象而不是细节

贯彻依赖倒置原则,左边能抽象,右边实例化的时候不能直接用抽象,所以需要借助第三方

高层本来是依赖低层,但是可以通过工厂(容器)来决定细节,去掉对低层的依赖。

IOC(Inversion of Control)控制反转:把高层对低层的依赖,转移到第三方决定,避免高层的直接依赖,那么程序架构就具备良好的扩展性和稳定性

DI(Dependency Injection) 依赖注入:是用来实现IOC的一种手段

在构造对象时,可以自动化的取初始化,对象需要的其他对象(构造函数注入、属性注入、方法注入)

不管是什么注入,都是通过反射来实现的

有了依赖注入,才能做到无限层级的依赖抽象,才能做到控制反转

1.2 分层的意义

分层是必须的

为什么分层:

1、职责清晰,方便分工合作

2、代码复用

3、体积小、方便维护

2 Unity的使用

2.1 安装


  1. install-package Unity
  2. install-package Unity.Interception
  3. install-package Unity.Interception.Configuration

2.2 Unity容器初步运用

//1、声明一个容器
IUnityContainer container = new UnityContainer();
//2、初始化容器,注册类型
container.RegisterType<IPhone, AndroidPhone>();

//3、创建对象,通过反射实现
IPhone phone = container.Resolve<IPhone>();
phone.Call();

2.3 Unity多种注册,一对多的注册

//1、声明一个容器
IUnityContainer container = new UnityContainer();
//2、初始化容器,注册类型
container.RegisterType<IPhone, AndroidPhone>();//接口


container.RegisterType<ApplePad, ApplePadChild>();//父子类

//container.RegisterType<AbstractPad, ApplePad>();//抽象类和子类
//container.RegisterType<AbstractPad, ApplePadChild>();//会覆盖 要想不被覆盖 传入形参


container.RegisterType<AbstractPad, ApplePad>("child");//抽象类和子类 一对多
container.RegisterType<AbstractPad, ApplePadChild>("GrandChild");

container.RegisterInstance<ITV>(new AppleTV(123));//注册实例,不常用(因为依赖细节了)

//3、创建对象,通过反射实现
IPhone phone = container.Resolve<IPhone>();
phone.Call();

//AbstractPad pad = container.Resolve<AbstractPad>();
ApplePad applePad = container.Resolve<ApplePad>();

AbstractPad childPad = container.Resolve<AbstractPad>("child");
childPad.Show();
AbstractPad GrandChildPad = container.Resolve<AbstractPad>("GrandChild");
childPad.Show();
ITV iTV = container.Resolve<ITV>();
iTV.Show();

2.4 Unity依赖注入,多层架构

1、声明一个容器
IUnityContainer container = new UnityContainer();
//2、初始化容器,注册类型
container.RegisterType<IPhone, ApplePhone>();
container.RegisterType<IMicrophone, Microphone>();
container.RegisterType<IPower, Power>();
container.RegisterType<IHeadphone, Headphone>();

//3、创建对象,通过反射实现
IPhone phone = container.Resolve<IPhone>();
phone.Call();

2.5 Unity生命周期管理

//容器成了创建对象的入口,可以加入自己的管理逻辑:生命周期
//1、声明一个容器
IUnityContainer container = new UnityContainer();
//2、初始化容器,注册类型
//container.RegisterType<IPhone, AndroidPhone>();//默认 瞬时

//container.RegisterType<IPhone, AndroidPhone>(new TransientLifetimeManager());//瞬时 每一次都是全新生成

// container.RegisterType<IPhone, AndroidPhone>(new ContainerControlledLifetimeManager());//容器单例 单例就是不要自己实现


//3、创建对象,通过反射实现
//IPhone phone1 = container.Resolve<IPhone>();
//IPhone phone2 = container.Resolve<IPhone>();
//Console.WriteLine(object.ReferenceEquals(phone1, phone2));
//phone1.Call();

#region 线程单例
//线程单例,相同线程的实例相同,不同线程的实例不同, 如web请求/多线程操作
container.RegisterType<IPhone, AndroidPhone>(new PerThreadLifetimeManager());//线程单例 同一个线程就是单例的 不同线程就是不同的
IPhone phone1 = null;
Action action1 = new Action(() =>
{
phone1 = container.Resolve<IPhone>();
Console.WriteLine($"iphone1由线程ID={Thread.CurrentThread.ManagedThreadId}");
});
var result1 = action1.BeginInvoke(null, null);

IPhone phone2 = null;
Action action2 = new Action(() =>
{
phone2 = container.Resolve<IPhone>();
Console.WriteLine($"iphone2由线程ID={Thread.CurrentThread.ManagedThreadId}");
});


IPhone phone3 = null;
var result2 = action2.BeginInvoke(t =>
{
phone3 = container.Resolve<IPhone>();
Console.WriteLine($"iphone3由线程ID={Thread.CurrentThread.ManagedThreadId}");
Console.WriteLine($"object.ReferenceEquals(phone2, phone3) = {object.ReferenceEquals(phone2, phone3)}");
}, null);

action1.EndInvoke(result1);
action2.EndInvoke(result2);

Console.WriteLine($"object.ReferenceEquals(phone1, phone2) = {object.ReferenceEquals(phone1, phone2)}");
#endregion


//container.RegisterType<IPhone, AndroidPhone>(new HierarchicalLifetimeManager());//分级容器单例
//IUnityContainer unityContainer = container.CreateChildContainer();//获取子容器

//container.RegisterType<IPhone, AndroidPhone>(new ExternallyControlledLifetimeManager());//外部可释放单例
//container.RegisterType<IPhone, AndroidPhone>(new PerResolveLifetimeManager());//循环引用 不推荐

3 AOP面向切面编程

<!--<?xml version="1.0" encoding="utf-8" ?>-->
<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="testContainer">
<extension type="Interception"/>
<register type="面向切面编程.UnityWay.IUserProcessor,面向切面编程" mapTo="面向切面编程.UnityWay.UserProcessor, 面向切面编程">
<interceptor type="InterfaceInterceptor"/>
<interceptionBehavior type="面向切面编程.UnityWay.ExceptionLoggingBehavior,面向切面编程"/>
<interceptionBehavior type="面向切面编程.UnityWay.CachingBehavior,面向切面编程"/>
<interceptionBehavior type="面向切面编程.UnityWay.LogBeforeBehavior,面向切面编程"/>
<interceptionBehavior type="面向切面编程.UnityWay.ParameterCheckBehavior,面向切面编程"/>
<interceptionBehavior type="面向切面编程.UnityWay.LogAfterBehavior,面向切面编程"/>
</register>
</container>
</containers>
</unity>

</configuration>
public class ParameterCheckBehavior : IInterceptionBehavior
{
public bool WillExecute
{
get
{
//throw new NotImplementedException();
return true;
}
}

public IEnumerable<Type> GetRequiredInterfaces()
{
//throw new NotImplementedException();
return Type.EmptyTypes;
}

public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
//throw new NotImplementedException();
Console.WriteLine("ParameterCheckBehavior");
User user = input.Inputs[0] as User;//可以不写死,反射+特性完成对数据的有效性检测
if (user.Pwd.Length<5)
{
//返回一个异常
return input.CreateExceptionMethodReturn(new Exception("密码长度不能小于10"));
}
else
{
return getNext().Invoke(input, getNext);
}
}
}
public class CachingBehavior : IInterceptionBehavior
{
private static Dictionary<string, object> CachingDictionary = new Dictionary<string, object>();

public bool WillExecute
{
get
{
//throw new NotImplementedException();
return true;
}
}

public IEnumerable<Type> GetRequiredInterfaces()
{
//throw new NotImplementedException();
return Type.EmptyTypes;
}

public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
//throw new NotImplementedException();
Console.WriteLine("CachingBehavior");
string key = $"{input.MethodBase.Name}_{Newtonsoft.Json.JsonConvert.SerializeObject(input.Inputs)}";
if (CachingDictionary.ContainsKey(key))
{
return input.CreateMethodReturn(CachingDictionary[key]);//相当于短路器 ,直接返回
}
else
{
IMethodReturn methodReturn = getNext().Invoke(input, getNext);
if (methodReturn.ReturnValue!=null)
{
CachingDictionary.Add(key, methodReturn.ReturnValue);
}
return methodReturn;
}
}
}
public class ExceptionLoggingBehavior : IInterceptionBehavior
{
public bool WillExecute
{
get
{
//throw new NotImplementedException();
return true;
}
}

public IEnumerable<Type> GetRequiredInterfaces()
{
//throw new NotImplementedException();
return Type.EmptyTypes;
}

public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
//throw new NotImplementedException();
IMethodReturn methodReturn = getNext().Invoke(input, getNext);
Console.WriteLine("ExceptionLoggingBehavior");
if (methodReturn.Exception==null)
{
Console.WriteLine("无异常");
}
else
{
Console.WriteLine($"异常:{methodReturn.Exception.Message}");
}
return methodReturn;
}
}
public class LogAfterBehavior : IInterceptionBehavior
{
public bool WillExecute
{
get
{
return true;
//throw new NotImplementedException();
}
}

public IEnumerable<Type> GetRequiredInterfaces()
{
//throw new NotImplementedException();
return Type.EmptyTypes;
}

public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
//throw new NotImplementedException();
IMethodReturn methodReturn = getNext().Invoke(input, getNext);
Console.WriteLine("LogAfterBehavior");
Console.WriteLine(input.MethodBase.Name);//获取方法名称
foreach (var item in input.Inputs)
{
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(item));
}
Console.WriteLine($"返回值:{methodReturn.ReturnValue}");
return methodReturn;
}

}
public class LogBeforeBehavior : IInterceptionBehavior
{
public bool WillExecute
{
get
{
return true;
//throw new NotImplementedException();
}
}

public IEnumerable<Type> GetRequiredInterfaces()
{
// throw new NotImplementedException();
return Type.EmptyTypes;
}

public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
// throw new NotImplementedException();
Console.WriteLine("LogBeforeBehavior");

//input拿到所有参数信息
foreach (var item in input.Inputs)
{
//反射或者序列化显示更多信息//install-package Newtonsoft.Json
Console.WriteLine(Newtonsoft.Json.JsonConvert.SerializeObject(item));//install-package Newtonsoft.Json
}
//
return getNext()(input, getNext);//getNext()得到委托实例;
}
}
public class UnityConfigAOP
{
public static void Show()
{
User user = new User() { Name = "Admin", Pwd = "123" };

{
//通过反射创建对象
IUnityContainer container = new UnityContainer();
container.RegisterType<IUserProcessor, UserProcessor>();
IUserProcessor processor = container.Resolve<IUserProcessor>();
processor.RegUser(user);
}

{
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 unityConfigurationSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
unityConfigurationSection.Configure(container, "testContainer");

IUserProcessor processor = container.Resolve<IUserProcessor>();
processor.RegUser(user);
}

}
}

public interface IUserProcessor
{
void RegUser(User user);
}

public class UserProcessor : IUserProcessor
{
public void RegUser(User user)
{
Console.WriteLine($"用户已注册,用户名称={user.Name} Password={user.Pwd}");
}
}

public class User
{
public string Name { get; set; }
public string Pwd { get; set; }
}