IOC():控制反转,把程序上层对下层的依赖,转移到第三方的容器来装配
是程序设计的目标,实现方式包含了依赖注入和依赖查找(.net里面只有依赖注入)
DI:依赖注入,是IOC的实习方式。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Unity;
using ZEN.Interface;
using ZEN.Service;
namespace UnityIOC
{
class Program
{
static void Main(string[] args)
{
//定义一个IOC容器
IUnityContainer container = new UnityContainer();
//添加映射关系
container.RegisterType<ICar, TeslaCar>();
//获取服务
var car = container.Resolve<ICar>();
car.GetName();
car.GetPrice();
car.GetMaxSpeed();
Console.ReadKey();
}
}
}
一个接口多个实现进行注册
如: 接口 IPhone
实现华为手机 继承 IPhone
实现苹果手机 继承 IPhone
IUnityContainer container = new UnityContainer();//1、定义一个空容器
container.RegisterType<IPhone, HuaweiPhone>(“huawei”);//2、注册类型,表示遇到IDbInterface的类型,创建DbMSSQL的实例
container.RegisterType<IPhone, ApplePhone>(“apple”);//表示遇到IDbInterface的类型,创建DbMSSQL的实例
var huawei= container.Resolve(“huawei”);
var apple= container.Resolve(“apple”);
Console.WriteLine(huawei.xxx());
Console.WriteLine(apple.xxx());
以上还是依赖细节,完全脱离细节,需要用配置文件,跟autofac一样
这样每次生成,才会把配置文件生成到bin目录下
会发现,如果改成使用配置文件的方式实现的话,代码里面就不会依赖于细节了,只要一个接口类型。既然没有细节了,那么对项目进行如下的改造:把引用里面对细节的引用都去掉(ZEN.Service),然后Debug文件夹里面没有这个DLL了,但是这时需要把这个DLL复制到Debug目录下面,否则程序运行的时候会找不到具体实现的类型。这样就意味着程序架构只依赖于接口。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Unity.Configuration" />
</configSections>
<unity>
<typeAliases>
<typeAlias alias="IPhone" type="ZEN.Interface.IPhone,ZEN.Interface"></typeAlias >
<typeAlias alias="IWork" type="ZEN.Interface.IWork,ZEN.Interface"></typeAlias >
<typeAlias alias="IPower" type="ZEN.Interface.IPower,ZEN.Interface"></typeAlias >
<typeAlias alias="ICar" type="ZEN.Interface.ICar,ZEN.Interface"></typeAlias >
<typeAlias alias="Phone" type="ZEN.Service.Phone,ZEN.Service"></typeAlias >
<typeAlias alias="Work" type="ZEN.Service.Work,ZEN.Service"></typeAlias >
<typeAlias alias="Power" type="ZEN.Service.Power,ZEN.Service"></typeAlias >
<typeAlias alias="Car" type="ZEN.Service.TeslaCar,ZEN.Service"></typeAlias >
</typeAliases>
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration" />
<containers>
<container name="testContainer">
<register type="IPhone" mapTo="Phone" />
<register type="IPower" mapTo="Power" />
<register type="ICar" mapTo="Car" name="tesla" >
<property name="work" dependencyType="IWork" />
<property name="phone" dependencyType="IPhone" />
</register>
<register type="IWork" mapTo="Work" />
</container>
</containers>
</unity>
</configuration>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Unity;
using ZEN.Interface;
using System.Configuration;
using Microsoft.Practices.Unity.Configuration;
using Unity.Interception;
using Unity.Interception.Interceptors.InstanceInterceptors.InterfaceInterception;
using Microsoft.Practices.Unity;
namespace UnityIOC
{
class Program
{
static void Main(string[] args)
{
//{ //定义一个IOC容器
// IUnityContainer container = new UnityContainer();
// //添加映射关系
// container.RegisterType<ICar, TeslaCar>("tesla");
// container.RegisterType<ICar, XiaoMICar>("xiaomi");
// container.RegisterType<IWork, Work>();
// container.RegisterType<IPower, Power>();
// container.RegisterType<IPhone, Phone>();
// //获取服务
// var car = container.Resolve<ICar>("tesla");
// car.GetName();
// car.GetPrice();
// car.GetMaxSpeed();
//}
{
//ExeConfigurationFileMap 要引入 System.Configuration;
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");//找配置文件的路径
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
IUnityContainer container = new UnityContainer();
section.Configure(container, "testContainer");
var car = container.Resolve<ICar>("tesla");
car.GetName();
car.GetPrice();
car.GetMaxSpeed();
//
}
Console.ReadKey();
}
}
}
构造函数注入、属性注入、方法注入 配置文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Unity.Configuration" />
</configSections>
<unity>
<typeAliases>
<typeAlias alias="IPhone" type="ZEN.Interface.IPhone,ZEN.Interface"></typeAlias >
<typeAlias alias="IWork" type="ZEN.Interface.IWork,ZEN.Interface"></typeAlias >
<typeAlias alias="IPower" type="ZEN.Interface.IPower,ZEN.Interface"></typeAlias >
<typeAlias alias="ICar" type="ZEN.Interface.ICar,ZEN.Interface"></typeAlias >
<typeAlias alias="Phone" type="ZEN.Service.Phone,ZEN.Service"></typeAlias >
<typeAlias alias="Work" type="ZEN.Service.Work,ZEN.Service"></typeAlias >
<typeAlias alias="Power" type="ZEN.Service.Power,ZEN.Service"></typeAlias >
<typeAlias alias="Car" type="ZEN.Service.TeslaCar,ZEN.Service"></typeAlias >
</typeAliases>
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration" />
<containers>
<container name="testContainer">
<register type="IPhone" mapTo="Phone" />
<register type="IPower" mapTo="Power" />
<register type="ICar" mapTo="Car" name="tesla" >
<property name="work" dependencyType="IWork" />
<property name="phone" dependencyType="IPhone" />
<method name="InitIphone">
<param name="_power" type="IPower" />
<param name="val" type="int" value="33"/>
</method>
</register>
<register type="IWork" mapTo="Work" />
</container>
</containers>
</unity>
</configuration>
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");//找配置文件的路径
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
IUnityContainer container = new UnityContainer();
section.Configure(container, "testContainer");
var car = container.Resolve<ICar>("tesla");
car.GetName();
car.GetPrice();
car.GetMaxSpeed();
unity IOC 源码
Unity AOP
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Unity.Configuration" />
</configSections>
<unity>
<typeAliases>
<typeAlias alias="IPhone" type="ZEN.Interface.IPhone,ZEN.Interface"></typeAlias >
<typeAlias alias="IWork" type="ZEN.Interface.IWork,ZEN.Interface"></typeAlias >
<typeAlias alias="IPower" type="ZEN.Interface.IPower,ZEN.Interface"></typeAlias >
<typeAlias alias="ICar" type="ZEN.Interface.ICar,ZEN.Interface"></typeAlias >
<typeAlias alias="Phone" type="ZEN.Service.Phone,ZEN.Service"></typeAlias >
<typeAlias alias="Work" type="ZEN.Service.Work,ZEN.Service"></typeAlias >
<typeAlias alias="Power" type="ZEN.Service.Power,ZEN.Service"></typeAlias >
<typeAlias alias="Car" type="ZEN.Service.TeslaCar,ZEN.Service"></typeAlias >
</typeAliases>
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration" />
<containers>
<container name="testContainer">
<!AOP 需要添加这个节点 <extension type="Interception"/>/>-->
<extension type="Interception"/>
<register type="IPhone" mapTo="Phone" />
<register type="IPower" mapTo="Power" />
<register type="ICar" mapTo="Car" name="tesla" >
<property name="work" dependencyType="IWork" />
<property name="phone" dependencyType="IPhone" />
<method name="InitIphone">
<param name="_power" type="IPower" />
<param name="val" type="int" value="33"/>
</method>
<interceptor type="InterfaceInterceptor"/>
<interceptionBehavior type="IOC.Common.IOC_AOP.AOP, IOC.Common"/>
</register>
<register type="IWork" mapTo="Work" />
</container>
</containers>
</unity>
</configuration>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Unity.Interception.InterceptionBehaviors;
using Unity.Interception.PolicyInjection.Pipeline;
namespace IOC.Common.IOC_AOP
{
/// <summary>
/// 不需要特性
/// </summary>
public class AOP : IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("IOC-AOP触发");
return getNext().Invoke(input, getNext);
}
}
}
MVC中的Filter过滤器也起到AOP功能,但与unity的AOP
有所不同
mvc中的过滤器是针对action的,action前,action后
unity框架的AOP 可以针对 方法
Filter可以在action前 后 异常都扩展逻辑 AOP—针对action完整方法
Unity容器的AOP也是需要的, AOP—针对方法里面的业务层扩展的